Skip to content

Commit 4ddce79

Browse files
EMaherCopilot
andcommitted
feat: add JSON schemas and Copilot prompts for filter/override configuration
- Add auto-generated JSON Schema files (schemas/extractor-config.schema.json, schemas/override-config.schema.json) for IDE autocompletion in YAML configs - Add scripts/generate-schemas.mjs that derives schemas from TypeScript interfaces and runs on every build/lint/test - Add Copilot prompt files (apiops-configure-filter, apiops-configure-overrides) that conversationally guide users through creating filter and override files - Update apiops init to lay down the new prompt files alongside identity setup - Include {#[TOKEN_NAME]#} placeholder syntax guidance and Key Vault patterns in the overrides prompt (per issue #117) - Update docs for filtering-resources, environment-overrides, and init command Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 18bc2be commit 4ddce79

18 files changed

Lines changed: 1240 additions & 9 deletions

docs/commands/init.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ In interactive mode (the default when running in a terminal), `apiops init` prom
8383
| `configuration.extractor.yaml` | Sample filter configuration for extraction |
8484
| `configuration.{env}.yaml` | Override templates per environment (e.g., `configuration.dev.yaml`, `configuration.prod.yaml`) |
8585
| `IDENTITY-SETUP-GITHUB.md` | Step-by-step guide for configuring federated credentials |
86+
| `.github/prompts/apiops-configure-filter.prompt.md` | Copilot prompt for configuring resource filters |
87+
| `.github/prompts/apiops-configure-overrides.prompt.md` | Copilot prompt for configuring environment overrides |
8688

8789
### Azure DevOps (`--ci azure-devops`)
8890

@@ -93,12 +95,16 @@ In interactive mode (the default when running in a terminal), `apiops init` prom
9395
| `configuration.extractor.yaml` | Sample filter configuration for extraction |
9496
| `configuration.{env}.yaml` | Override templates per environment |
9597
| `IDENTITY-SETUP-AZDO.md` | Step-by-step guide for configuring service connections |
98+
| `.github/prompts/apiops-configure-filter.prompt.md` | Copilot prompt for configuring resource filters |
99+
| `.github/prompts/apiops-configure-overrides.prompt.md` | Copilot prompt for configuring environment overrides |
96100

97101
### Both platforms
98102

99103
| File | Purpose |
100104
|------|---------|
101105
| `.github/prompts/apiops-setup-identity.prompt.md` | Copilot prompt for identity setup |
106+
| `.github/prompts/apiops-configure-filter.prompt.md` | Copilot prompt for creating extraction filter files |
107+
| `.github/prompts/apiops-configure-overrides.prompt.md` | Copilot prompt for creating environment override files |
102108
| `<artifact-dir>/` | Empty artifact directory (default: `./apim-artifacts`) |
103109

104110
## Package consumption modes
@@ -116,11 +122,24 @@ If you pass `--cli-package <path>`, the tarball is copied into a `.apiops/` dire
116122

117123
## Next steps after init
118124

119-
1. **Set up identity** — Follow the generated `IDENTITY-SETUP-*.md` guide to configure Azure credentials for your CI/CD platform.
125+
1. **Set up identity** — Follow the generated `IDENTITY-SETUP-*.md` guide to configure Azure credentials for your CI/CD platform. Or use the `.github/prompts/apiops-setup-identity.prompt.md` Copilot prompt.
120126
2. **Extract your first snapshot** — Run [`apiops extract`](./extract.md) to pull your current APIM configuration into the artifact directory.
121-
3. **Commit and push** — Check the generated files into version control.
122-
4. **Configure overrides** — Edit `configuration.{env}.yaml` files with environment-specific values. See the [environment overrides guide](../guides/environment-overrides.md).
123-
5. **Run your pipeline** — Trigger the publish pipeline to deploy artifacts to your target APIM instance.
127+
3. **Configure filters** — Edit `configuration.extractor.yaml` to control which resources are extracted. Use the `.github/prompts/apiops-configure-filter.prompt.md` Copilot prompt for guided setup.
128+
4. **Commit and push** — Check the generated files into version control.
129+
5. **Configure overrides** — Edit `configuration.{env}.yaml` files with environment-specific values. Use the `.github/prompts/apiops-configure-overrides.prompt.md` Copilot prompt for guided setup. See the [environment overrides guide](../guides/environment-overrides.md).
130+
6. **Run your pipeline** — Trigger the publish pipeline to deploy artifacts to your target APIM instance.
131+
132+
## JSON Schemas for IDE Autocomplete
133+
134+
Generated `configuration.extractor.yaml` and `configuration.{env}.yaml` files include a YAML language server schema comment that provides IDE autocomplete when editing:
135+
136+
```yaml
137+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/apiops-cli/main/schemas/extractor-config.schema.json
138+
```
139+
140+
The schemas are available at:
141+
- **Filter config:** [`schemas/extractor-config.schema.json`](https://github.com/Azure/apiops-cli/blob/main/schemas/extractor-config.schema.json)
142+
- **Override config:** [`schemas/override-config.schema.json`](https://github.com/Azure/apiops-cli/blob/main/schemas/override-config.schema.json)
124143

125144
## Related docs
126145

docs/guides/environment-overrides.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ apiops publish \
2323
--overrides ./configuration.prod.yaml
2424
```
2525

26+
## IDE Autocomplete (JSON Schema)
27+
28+
Add this comment as the first line of your override file to enable autocomplete in VS Code and other YAML-aware editors:
29+
30+
```yaml
31+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/apiops-cli/main/schemas/override-config.schema.json
32+
```
33+
34+
The schema validates section names, entry structure, nested sub-resource overrides, and supports `{#[TOKEN_NAME]#}` placeholder values. It is published at [`schemas/override-config.schema.json`](https://github.com/Azure/apiops-cli/blob/main/schemas/override-config.schema.json).
35+
2636
## Override file format (APIOps Toolkit-compatible)
2737

2838
`apiops-cli` uses the [APIOps Toolkit](https://github.com/Azure/apiops) override layout:
@@ -482,3 +492,24 @@ apiops publish --overrides configuration.prod.yaml --dry-run \
482492
- [Authentication Guide](authentication.md)
483493
- [Scenarios and Workflows](scenarios-and-workflows.md)
484494
- [GitHub Actions Integration](../ci-cd/github-actions.md)
495+
496+
---
497+
498+
## JSON Schema and Copilot Prompt
499+
500+
### IDE Autocompletion with JSON Schema
501+
502+
A JSON Schema is available for `configuration.{env}.yaml` override files. Add this comment at the top of your override file to enable autocompletion in VS Code (with the YAML extension):
503+
504+
```yaml
505+
# yaml-language-server: $schema=./schemas/override-config.schema.json
506+
```
507+
508+
The schema provides:
509+
- Property name autocompletion for all resource sections
510+
- Validation of the override structure (name + properties format)
511+
- Inline documentation including token substitution syntax
512+
513+
### Copilot-Assisted Configuration
514+
515+
If you ran `apiops init`, a Copilot prompt file was generated at `.github/prompts/apiops-configure-overrides.prompt.md`. Open it in VS Code and ask GitHub Copilot to help you configure environment overrides — it will guide you through setting up environment-specific values interactively.

docs/guides/filtering-resources.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ Only `petstore-api`, `orders-api`, and their transitive dependencies are extract
3636

3737
---
3838

39+
## IDE Autocomplete (JSON Schema)
40+
41+
Add this comment as the first line of your filter file to enable autocomplete in VS Code and other YAML-aware editors:
42+
43+
```yaml
44+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/apiops-cli/main/schemas/extractor-config.schema.json
45+
```
46+
47+
The schema validates field names, array structure, and sub-resource filters. It is published at [`schemas/extractor-config.schema.json`](https://github.com/Azure/apiops-cli/blob/main/schemas/extractor-config.schema.json).
48+
49+
---
50+
3951
## Filter YAML Format
4052

4153
The filter file is a YAML document where each key is a resource type and the value is an array of resource names:
@@ -336,3 +348,24 @@ backends:
336348
- [Environment Overrides](environment-overrides.md) — per-environment configuration
337349
- [Configuration Reference](../reference/configuration.md) — config priority chain
338350
- [APIM Glossary](../reference/apim-glossary.md) — APIM resource terminology
351+
352+
---
353+
354+
## JSON Schema and Copilot Prompt
355+
356+
### IDE Autocompletion with JSON Schema
357+
358+
A JSON Schema is available for `configuration.extractor.yaml` files. Add this comment at the top of your filter file to enable autocompletion in VS Code (with the YAML extension):
359+
360+
```yaml
361+
# yaml-language-server: $schema=./schemas/extractor-config.schema.json
362+
```
363+
364+
The schema provides:
365+
- Property name autocompletion for all resource types
366+
- Validation of the filter structure
367+
- Inline documentation for each field
368+
369+
### Copilot-Assisted Configuration
370+
371+
If you ran `apiops init`, a Copilot prompt file was generated at `.github/prompts/apiops-configure-filter.prompt.md`. Open it in VS Code and ask GitHub Copilot to help you configure your filter — it will walk you through selecting resources interactively.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
],
1515
"readme": "README.md",
1616
"scripts": {
17-
"prelint": "node scripts/embed-markdown-templates.mjs",
18-
"prebuild": "node scripts/embed-markdown-templates.mjs",
19-
"pretest": "node scripts/embed-markdown-templates.mjs",
17+
"prelint": "node scripts/embed-markdown-templates.mjs && node scripts/generate-schemas.mjs",
18+
"prebuild": "node scripts/embed-markdown-templates.mjs && node scripts/generate-schemas.mjs",
19+
"pretest": "node scripts/embed-markdown-templates.mjs && node scripts/generate-schemas.mjs",
2020
"build": "tsc",
2121
"test": "vitest run",
2222
"test:watch": "vitest",
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$comment": "Copyright (c) Microsoft Corporation. Licensed under the MIT license.",
4+
"$id": "https://github.com/Azure/apiops-cli/schemas/extractor-config.schema.json",
5+
"title": "APIOps Filter Configuration",
6+
"description": "Validates configuration.extractor.yaml files used by APIOps CLI to select which Azure API Management resources are extracted. All resource sections are optional.",
7+
"type": "object",
8+
"additionalProperties": false,
9+
"properties": {
10+
"$schema": {
11+
"type": "string",
12+
"description": "Optional schema URI for editor and IDE validation."
13+
},
14+
"apis": {
15+
"type": "array",
16+
"description": "APIs to extract. Each item can be either a plain API name or wildcard pattern, or an object with a single API name mapped to nested API sub-filters. Matching is case-insensitive and supports * and ? wildcards.",
17+
"items": {
18+
"$ref": "#/definitions/apiSelector"
19+
}
20+
},
21+
"backends": {
22+
"$ref": "#/definitions/resourcePatternArray",
23+
"description": "Backends to extract. Matching is case-insensitive and supports * and ? wildcards."
24+
},
25+
"products": {
26+
"$ref": "#/definitions/resourcePatternArray",
27+
"description": "Products to extract. Matching is case-insensitive and supports * and ? wildcards."
28+
},
29+
"namedValues": {
30+
"$ref": "#/definitions/resourcePatternArray",
31+
"description": "Named values to extract. Matching is case-insensitive and supports * and ? wildcards."
32+
},
33+
"loggers": {
34+
"$ref": "#/definitions/resourcePatternArray",
35+
"description": "Loggers to extract. Matching is case-insensitive and supports * and ? wildcards."
36+
},
37+
"diagnostics": {
38+
"$ref": "#/definitions/resourcePatternArray",
39+
"description": "Diagnostics to extract. Matching is case-insensitive and supports * and ? wildcards."
40+
},
41+
"tags": {
42+
"$ref": "#/definitions/resourcePatternArray",
43+
"description": "Tags to extract. Matching is case-insensitive and supports * and ? wildcards."
44+
},
45+
"policyFragments": {
46+
"$ref": "#/definitions/resourcePatternArray",
47+
"description": "Policy fragments to extract. Matching is case-insensitive and supports * and ? wildcards."
48+
},
49+
"gateways": {
50+
"$ref": "#/definitions/resourcePatternArray",
51+
"description": "Gateways to extract. Matching is case-insensitive and supports * and ? wildcards."
52+
},
53+
"versionSets": {
54+
"$ref": "#/definitions/resourcePatternArray",
55+
"description": "Version sets to extract. Matching is case-insensitive and supports * and ? wildcards."
56+
},
57+
"groups": {
58+
"$ref": "#/definitions/resourcePatternArray",
59+
"description": "Groups to extract. Matching is case-insensitive and supports * and ? wildcards."
60+
},
61+
"subscriptions": {
62+
"$ref": "#/definitions/resourcePatternArray",
63+
"description": "Subscriptions to extract. Matching is case-insensitive and supports * and ? wildcards."
64+
},
65+
"schemas": {
66+
"$ref": "#/definitions/resourcePatternArray",
67+
"description": "Schemas to extract. Matching is case-insensitive and supports * and ? wildcards."
68+
},
69+
"policies": {
70+
"$ref": "#/definitions/resourcePatternArray",
71+
"description": "Service-level policies to extract. Matching is case-insensitive and supports * and ? wildcards."
72+
},
73+
"policyRestrictions": {
74+
"$ref": "#/definitions/resourcePatternArray",
75+
"description": "Policy restrictions to extract. Matching is case-insensitive and supports * and ? wildcards."
76+
},
77+
"documentations": {
78+
"$ref": "#/definitions/resourcePatternArray",
79+
"description": "Documentations to extract. Matching is case-insensitive and supports * and ? wildcards."
80+
},
81+
"workspaces": {
82+
"type": "array",
83+
"description": "Workspaces to extract. Each item can be either a plain workspace name or wildcard pattern, or an object with a single workspace name mapped to nested workspace sub-filters. Matching is case-insensitive and supports * and ? wildcards.",
84+
"items": {
85+
"$ref": "#/definitions/workspaceSelector"
86+
}
87+
}
88+
},
89+
"definitions": {
90+
"resourcePattern": {
91+
"type": "string",
92+
"description": "A resource name or wildcard pattern. Matching is case-insensitive. Supported wildcards: * matches zero or more characters, and ? matches a single character."
93+
},
94+
"resourcePatternArray": {
95+
"type": "array",
96+
"description": "A list of resource names or wildcard patterns. Matching is case-insensitive. Supported wildcards: * and ?.",
97+
"items": {
98+
"$ref": "#/definitions/resourcePattern"
99+
}
100+
},
101+
"apiSelector": {
102+
"oneOf": [
103+
{
104+
"$ref": "#/definitions/resourcePattern"
105+
},
106+
{
107+
"type": "object",
108+
"description": "A single API name mapped to sub-resource filters for that API.",
109+
"minProperties": 1,
110+
"maxProperties": 1,
111+
"patternProperties": {
112+
"^.+$": {
113+
"$ref": "#/definitions/apiSubFilter"
114+
}
115+
},
116+
"additionalProperties": false
117+
}
118+
]
119+
},
120+
"workspaceSelector": {
121+
"oneOf": [
122+
{
123+
"$ref": "#/definitions/resourcePattern"
124+
},
125+
{
126+
"type": "object",
127+
"description": "A single workspace name mapped to sub-resource filters for that workspace.",
128+
"minProperties": 1,
129+
"maxProperties": 1,
130+
"patternProperties": {
131+
"^.+$": {
132+
"$ref": "#/definitions/workspaceSubFilter"
133+
}
134+
},
135+
"additionalProperties": false
136+
}
137+
]
138+
},
139+
"apiSubFilter": {
140+
"type": "object",
141+
"description": "Sub-resource filters for a specific API. Omit a property to include all sub-resources of that type, or set it to an empty array to exclude all of that type. Matching is case-insensitive and supports * and ? wildcards.",
142+
"additionalProperties": false,
143+
"properties": {
144+
"operations": {
145+
"$ref": "#/definitions/resourcePatternArray",
146+
"description": "Operations to extract for this API. Matching is case-insensitive and supports * and ? wildcards."
147+
},
148+
"diagnostics": {
149+
"$ref": "#/definitions/resourcePatternArray",
150+
"description": "Diagnostics to extract for this API. Matching is case-insensitive and supports * and ? wildcards."
151+
},
152+
"schemas": {
153+
"$ref": "#/definitions/resourcePatternArray",
154+
"description": "Schemas to extract for this API. Matching is case-insensitive and supports * and ? wildcards."
155+
},
156+
"releases": {
157+
"$ref": "#/definitions/resourcePatternArray",
158+
"description": "Releases to extract for this API. Matching is case-insensitive and supports * and ? wildcards."
159+
}
160+
}
161+
},
162+
"workspaceSubFilter": {
163+
"type": "object",
164+
"description": "Sub-resource filters for a specific workspace. Omit a property to include all resources of that type, or set it to an empty array to exclude all of that type. Matching is case-insensitive and supports * and ? wildcards.",
165+
"additionalProperties": false,
166+
"properties": {
167+
"apis": {
168+
"type": "array",
169+
"description": "APIs within this workspace to extract. Each item can be either a plain API name or wildcard pattern, or an object with a single API name mapped to nested API sub-filters. Matching is case-insensitive and supports * and ? wildcards.",
170+
"items": {
171+
"$ref": "#/definitions/apiSelector"
172+
}
173+
},
174+
"backends": {
175+
"$ref": "#/definitions/resourcePatternArray",
176+
"description": "Backends within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
177+
},
178+
"diagnostics": {
179+
"$ref": "#/definitions/resourcePatternArray",
180+
"description": "Diagnostics within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
181+
},
182+
"groups": {
183+
"$ref": "#/definitions/resourcePatternArray",
184+
"description": "Groups within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
185+
},
186+
"loggers": {
187+
"$ref": "#/definitions/resourcePatternArray",
188+
"description": "Loggers within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
189+
},
190+
"namedValues": {
191+
"$ref": "#/definitions/resourcePatternArray",
192+
"description": "Named values within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
193+
},
194+
"policyFragments": {
195+
"$ref": "#/definitions/resourcePatternArray",
196+
"description": "Policy fragments within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
197+
},
198+
"products": {
199+
"$ref": "#/definitions/resourcePatternArray",
200+
"description": "Products within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
201+
},
202+
"schemas": {
203+
"$ref": "#/definitions/resourcePatternArray",
204+
"description": "Schemas within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
205+
},
206+
"subscriptions": {
207+
"$ref": "#/definitions/resourcePatternArray",
208+
"description": "Subscriptions within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
209+
},
210+
"tags": {
211+
"$ref": "#/definitions/resourcePatternArray",
212+
"description": "Tags within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
213+
},
214+
"versionSets": {
215+
"$ref": "#/definitions/resourcePatternArray",
216+
"description": "Version sets within this workspace to extract. Matching is case-insensitive and supports * and ? wildcards."
217+
}
218+
}
219+
}
220+
}
221+
}

0 commit comments

Comments
 (0)