ado-sync 0.1.24 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -678
- package/dist/azure/client.d.ts +3 -0
- package/dist/azure/client.js +6 -0
- package/dist/azure/client.js.map +1 -1
- package/dist/azure/test-cases.d.ts +8 -3
- package/dist/azure/test-cases.js +406 -25
- package/dist/azure/test-cases.js.map +1 -1
- package/dist/cli.js +51 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.js +111 -5
- package/dist/config.js.map +1 -1
- package/dist/parsers/csharp.d.ts +30 -0
- package/dist/parsers/csharp.js +257 -0
- package/dist/parsers/csharp.js.map +1 -0
- package/dist/parsers/gherkin.d.ts +4 -1
- package/dist/parsers/gherkin.js +19 -4
- package/dist/parsers/gherkin.js.map +1 -1
- package/dist/parsers/java.d.ts +40 -0
- package/dist/parsers/java.js +329 -0
- package/dist/parsers/java.js.map +1 -0
- package/dist/parsers/javascript.d.ts +33 -0
- package/dist/parsers/javascript.js +261 -0
- package/dist/parsers/javascript.js.map +1 -0
- package/dist/parsers/markdown.d.ts +4 -1
- package/dist/parsers/markdown.js +5 -3
- package/dist/parsers/markdown.js.map +1 -1
- package/dist/parsers/python.d.ts +34 -0
- package/dist/parsers/python.js +305 -0
- package/dist/parsers/python.js.map +1 -0
- package/dist/parsers/shared.d.ts +18 -0
- package/dist/parsers/shared.js +40 -0
- package/dist/parsers/shared.js.map +1 -1
- package/dist/sync/engine.js +114 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/publish-results.d.ts +49 -0
- package/dist/sync/publish-results.js +476 -0
- package/dist/sync/publish-results.js.map +1 -0
- package/dist/sync/writeback.d.ts +57 -1
- package/dist/sync/writeback.js +243 -0
- package/dist/sync/writeback.js.map +1 -1
- package/dist/types.d.ts +159 -2
- package/docs/advanced.md +350 -0
- package/docs/configuration.md +293 -0
- package/docs/publish-test-results.md +317 -0
- package/docs/spec-formats.md +595 -0
- package/package.json +1 -1
package/docs/advanced.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Advanced configuration
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Format configuration
|
|
6
|
+
|
|
7
|
+
`sync.format` controls how test case content is structured when pushed to Azure DevOps.
|
|
8
|
+
|
|
9
|
+
| Field | Default | Description |
|
|
10
|
+
|-------|---------|-------------|
|
|
11
|
+
| `prefixTitle` | `true` | Prefix TC title with `"Scenario: "` or `"Scenario Outline: "`. Set `false` to use the raw scenario name. |
|
|
12
|
+
| `prefixBackgroundSteps` | `true` | Include Background steps in the TC steps list, prefixed with `"Background: "`. Set `false` to exclude them. |
|
|
13
|
+
| `useExpectedResult` | `false` | When `true`, `Then`/`Verify` steps are moved to the Expected Result column instead of the Action column. |
|
|
14
|
+
| `syncDataTableAsText` | `false` | When `true`, inline Gherkin data tables are appended to the step action as plain `\| cell \| cell \|` text instead of being handled as sub-steps. |
|
|
15
|
+
| `showParameterListStep` | `"whenUnusedParameters"` | Append a `Parameters: @p1@, @p2@, ...` step to parametrized TCs. `"always"` — always append. `"never"` — never append. `"whenUnusedParameters"` — append only when at least one parameter is not already referenced in a step. |
|
|
16
|
+
| `emptyActionValue` | *(blank)* | Value to use when a step action would be empty (e.g. when `useExpectedResult` moves a step to the expected column). |
|
|
17
|
+
| `emptyExpectedResultValue` | *(blank)* | Value to use when the expected result column would be empty. |
|
|
18
|
+
|
|
19
|
+
### Example
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"sync": {
|
|
24
|
+
"format": {
|
|
25
|
+
"prefixTitle": false,
|
|
26
|
+
"useExpectedResult": true,
|
|
27
|
+
"showParameterListStep": "always",
|
|
28
|
+
"emptyActionValue": "-"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## State configuration
|
|
37
|
+
|
|
38
|
+
`sync.state` sets the Azure Test Case `State` field whenever a scenario is created or updated.
|
|
39
|
+
|
|
40
|
+
| Field | Description |
|
|
41
|
+
|-------|-------------|
|
|
42
|
+
| `setValueOnChangeTo` | The state value to set, e.g. `"Design"`, `"Ready"`. |
|
|
43
|
+
| `condition` | *(Optional)* Tag expression. Only scenarios matching this expression trigger the state change. |
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"sync": {
|
|
48
|
+
"state": {
|
|
49
|
+
"setValueOnChangeTo": "Design",
|
|
50
|
+
"condition": "@active"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Field updates
|
|
59
|
+
|
|
60
|
+
`sync.fieldUpdates` applies custom field values on push. Each key is an Azure DevOps field reference name (e.g. `"System.AreaPath"`) or display name.
|
|
61
|
+
|
|
62
|
+
### Simple value (always set)
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"sync": {
|
|
67
|
+
"fieldUpdates": {
|
|
68
|
+
"Custom.AutomationStatus": "Automated",
|
|
69
|
+
"System.AreaPath": "MyProject\\QA Team"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Conditional value (switch by tag)
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"sync": {
|
|
80
|
+
"fieldUpdates": {
|
|
81
|
+
"System.AreaPath": {
|
|
82
|
+
"conditionalValue": {
|
|
83
|
+
"@smoke": "MyProject\\Smoke",
|
|
84
|
+
"@regression": "MyProject\\Regression",
|
|
85
|
+
"otherwise": "MyProject\\General"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Tag wildcard capture
|
|
94
|
+
|
|
95
|
+
Wildcard `*` captures the matched portion and exposes it as `{1}`, `{2}`, ... in the value.
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"sync": {
|
|
100
|
+
"fieldUpdates": {
|
|
101
|
+
"Custom.Priority": {
|
|
102
|
+
"condition": "@priority:*",
|
|
103
|
+
"value": "{1}"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
With tag `@priority:high`, this sets `Custom.Priority` to `"high"`.
|
|
111
|
+
|
|
112
|
+
### Update event
|
|
113
|
+
|
|
114
|
+
Control when the update fires:
|
|
115
|
+
|
|
116
|
+
| `update` | Behaviour |
|
|
117
|
+
|----------|-----------|
|
|
118
|
+
| `"always"` *(default)* | Apply on every push (create and update). |
|
|
119
|
+
| `"onCreate"` | Apply only when the TC is being created for the first time. |
|
|
120
|
+
| `"onChange"` | Apply only when the TC already exists and is being updated. |
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"sync": {
|
|
125
|
+
"fieldUpdates": {
|
|
126
|
+
"Custom.CreatedBySync": { "value": "true", "update": "onCreate" }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Placeholders
|
|
133
|
+
|
|
134
|
+
Value strings support these placeholders:
|
|
135
|
+
|
|
136
|
+
| Placeholder | Resolves to |
|
|
137
|
+
|-------------|-------------|
|
|
138
|
+
| `{scenario-name}` | Scenario title |
|
|
139
|
+
| `{feature-name}` | File name without extension |
|
|
140
|
+
| `{feature-file}` | File name with extension |
|
|
141
|
+
| `{scenario-description}` | Scenario description text |
|
|
142
|
+
| `{1}`, `{2}`, … | Wildcard captures from the `condition` |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Customizations
|
|
147
|
+
|
|
148
|
+
### Field defaults
|
|
149
|
+
|
|
150
|
+
Set default Azure field values applied only when a Test Case is **created** (not on updates).
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"customizations": {
|
|
155
|
+
"fieldDefaults": {
|
|
156
|
+
"enabled": true,
|
|
157
|
+
"defaultValues": {
|
|
158
|
+
"System.State": "Design",
|
|
159
|
+
"Custom.AutomationStatus": "Planned"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Ignore test case tags
|
|
167
|
+
|
|
168
|
+
Preserve Azure-side tags from being removed during push. Useful for tags managed by Azure DevOps workflows (e.g. `reviewed`, `approved`).
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"customizations": {
|
|
173
|
+
"ignoreTestCaseTags": {
|
|
174
|
+
"enabled": true,
|
|
175
|
+
"tags": ["reviewed", "ado-*"]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Patterns support a trailing `*` wildcard: `"ado-*"` matches any tag starting with `ado-`.
|
|
182
|
+
|
|
183
|
+
### Tag text map transformation
|
|
184
|
+
|
|
185
|
+
Apply character or substring replacements to tags before they are pushed to Azure DevOps.
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"customizations": {
|
|
190
|
+
"tagTextMapTransformation": {
|
|
191
|
+
"enabled": true,
|
|
192
|
+
"textMap": { "_": " " }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
With this config, `@my_feature_tag` is stored in Azure as `my feature tag`.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Attachments
|
|
203
|
+
|
|
204
|
+
Attach files to Test Cases via tags.
|
|
205
|
+
|
|
206
|
+
### Config
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"sync": {
|
|
211
|
+
"attachments": {
|
|
212
|
+
"enabled": true,
|
|
213
|
+
"tagPrefixes": ["wireframe", "spec"],
|
|
214
|
+
"baseFolder": "specs/attachments"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
| Field | Default | Description |
|
|
221
|
+
|-------|---------|-------------|
|
|
222
|
+
| `enabled` | `false` | Enable attachment sync. |
|
|
223
|
+
| `tagPrefixes` | `[]` | Additional tag prefixes beyond the built-in `attachment`. |
|
|
224
|
+
| `baseFolder` | *(feature file dir)* | Base directory for resolving file paths. Relative to config file. |
|
|
225
|
+
|
|
226
|
+
### Usage
|
|
227
|
+
|
|
228
|
+
```gherkin
|
|
229
|
+
@tc:1042 @attachment:screenshots/login.png @wireframe:mockups/login.fig
|
|
230
|
+
Scenario: Login page
|
|
231
|
+
...
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The default `attachment` prefix is always active when `enabled: true`. Additional prefixes are configured via `tagPrefixes`.
|
|
235
|
+
|
|
236
|
+
File paths support glob patterns: `@attachment:screenshots/*.png` attaches all matching files.
|
|
237
|
+
|
|
238
|
+
Files are uploaded to the Azure Work Item as attachments. Already-attached files (by name) are not re-uploaded.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Pull configuration
|
|
243
|
+
|
|
244
|
+
### Pull-create: generate local files from Azure
|
|
245
|
+
|
|
246
|
+
When `sync.pull.enableCreatingNewLocalTestCases` is `true`, a `pull` run will create new local spec files for Azure Test Cases that have no local counterpart (i.e. they exist in the configured suite but have no `@tc:ID` anywhere in the local files).
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"sync": {
|
|
251
|
+
"pull": {
|
|
252
|
+
"enableCreatingNewLocalTestCases": true,
|
|
253
|
+
"targetFolder": "specs/pulled"
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
| Field | Default | Description |
|
|
260
|
+
|-------|---------|-------------|
|
|
261
|
+
| `enableCreatingNewLocalTestCases` | `false` | When `true`, `pull` creates local files for unlinked Azure TCs. |
|
|
262
|
+
| `targetFolder` | `.` (config dir) | Directory where new files are created. Relative to config file. |
|
|
263
|
+
|
|
264
|
+
Generated files use the format matching `local.type` (`.feature` for Gherkin, `.md` for Markdown). The `@tc:ID` tag is written into the file so subsequent pushes link back to the same TC.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Suite hierarchy
|
|
269
|
+
|
|
270
|
+
By default, all Test Cases go into a single flat suite (`suiteMapping: "flat"`). Setting `suiteMapping: "byFolder"` mirrors the local folder structure as nested child suites in Azure.
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"testPlan": {
|
|
275
|
+
"id": 1234,
|
|
276
|
+
"suiteId": 5678,
|
|
277
|
+
"suiteMapping": "byFolder"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
specs/
|
|
284
|
+
login/
|
|
285
|
+
basic.feature → suite "login" → TC "Successful login"
|
|
286
|
+
checkout/
|
|
287
|
+
happy.feature → suite "checkout" → TC "Add item and checkout"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Child suites are created automatically if they do not exist. The suite hierarchy is re-used across runs.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Conflict detection
|
|
295
|
+
|
|
296
|
+
ado-sync uses a local state cache (`.ado-sync-state.json`) to detect conflicts — cases where **both** the local file and the Azure Test Case were changed since the last sync.
|
|
297
|
+
|
|
298
|
+
The `sync.conflictAction` setting controls what happens:
|
|
299
|
+
|
|
300
|
+
| Value | Behaviour |
|
|
301
|
+
|-------|-----------|
|
|
302
|
+
| `"overwrite"` *(default)* | Push local version to Azure, overwriting the remote change. |
|
|
303
|
+
| `"skip"` | Emit a `!` conflict result and leave both sides unchanged. |
|
|
304
|
+
| `"fail"` | Throw an error listing all conflicting scenarios and abort. |
|
|
305
|
+
|
|
306
|
+
```json
|
|
307
|
+
{ "sync": { "conflictAction": "skip" } }
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Commit `.ado-sync-state.json` to version control** so all team members and CI share the same last-synced state.
|
|
311
|
+
|
|
312
|
+
The cache also speeds up `push` — unchanged scenarios (same local hash + same Azure `changedDate`) are skipped without an API call.
|
|
313
|
+
|
|
314
|
+
To reset the cache: delete `.ado-sync-state.json`. The next push re-populates it from Azure.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## CI / build server mode
|
|
319
|
+
|
|
320
|
+
Set `sync.disableLocalChanges: true` to prevent ado-sync from writing back to local files:
|
|
321
|
+
|
|
322
|
+
- `push` — creates and updates Test Cases in Azure, but does **not** write ID tags to local files.
|
|
323
|
+
- `pull` — computes what would change but does **not** modify local files (behaves like `--dry-run`).
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{ "sync": { "disableLocalChanges": true } }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Or per-run via `--config-override`:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
ado-sync push --config-override sync.disableLocalChanges=true
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### GitHub Actions example
|
|
336
|
+
|
|
337
|
+
```yaml
|
|
338
|
+
- name: Sync test cases to Azure DevOps
|
|
339
|
+
run: ado-sync push --config-override sync.disableLocalChanges=true
|
|
340
|
+
env:
|
|
341
|
+
AZURE_DEVOPS_TOKEN: ${{ secrets.AZURE_DEVOPS_TOKEN }}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Removed scenario detection
|
|
347
|
+
|
|
348
|
+
When a scenario is deleted from a local file but its Test Case still exists in the Azure suite, ado-sync detects this on the next `push` and appends the tag `ado-sync:removed` to the Azure Test Case (without deleting it). A `−` removed line is printed in the output.
|
|
349
|
+
|
|
350
|
+
To completely remove the Test Case from Azure, delete it manually in Test Plans after reviewing.
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Configuration reference
|
|
2
|
+
|
|
3
|
+
Config files can be JSON (`.json`) or YAML (`.yml` / `.yaml`). Run `ado-sync init` to generate a template.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Full example (JSON)
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"orgUrl": "https://dev.azure.com/YOUR_ORG",
|
|
12
|
+
"project": "YOUR_PROJECT",
|
|
13
|
+
"configurationKey": "my-repo-smoke",
|
|
14
|
+
|
|
15
|
+
"auth": {
|
|
16
|
+
"type": "pat",
|
|
17
|
+
"token": "$AZURE_DEVOPS_TOKEN"
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
"testPlan": {
|
|
21
|
+
"id": 1234,
|
|
22
|
+
"suiteId": 5678,
|
|
23
|
+
"suiteMapping": "flat"
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"local": {
|
|
27
|
+
"type": "gherkin",
|
|
28
|
+
"include": "specs/**/*.feature",
|
|
29
|
+
"exclude": [],
|
|
30
|
+
"condition": "@done and not @wip"
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
"toolSettings": {
|
|
34
|
+
"parentConfig": "../base-ado-sync.json",
|
|
35
|
+
"outputLevel": "normal"
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
"sync": {
|
|
39
|
+
"tagPrefix": "tc",
|
|
40
|
+
"titleField": "System.Title",
|
|
41
|
+
"areaPath": "MyProject\\Team A",
|
|
42
|
+
"iterationPath": "MyProject\\Sprint 1",
|
|
43
|
+
"disableLocalChanges": false,
|
|
44
|
+
"conflictAction": "overwrite",
|
|
45
|
+
"links": [
|
|
46
|
+
{ "prefix": "story", "relationship": "System.LinkTypes.Related" },
|
|
47
|
+
{ "prefix": "bug", "relationship": "System.LinkTypes.Related" }
|
|
48
|
+
],
|
|
49
|
+
"state": {
|
|
50
|
+
"setValueOnChangeTo": "Design",
|
|
51
|
+
"condition": "@active"
|
|
52
|
+
},
|
|
53
|
+
"fieldUpdates": {
|
|
54
|
+
"System.AreaPath": {
|
|
55
|
+
"conditionalValue": {
|
|
56
|
+
"@smoke": "MyProject\\Smoke",
|
|
57
|
+
"otherwise": "MyProject\\Regression"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"Custom.Priority": {
|
|
61
|
+
"condition": "@priority:*",
|
|
62
|
+
"value": "{1}",
|
|
63
|
+
"update": "onCreate"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"format": {
|
|
67
|
+
"prefixTitle": true,
|
|
68
|
+
"prefixBackgroundSteps": true,
|
|
69
|
+
"useExpectedResult": false,
|
|
70
|
+
"syncDataTableAsText": false,
|
|
71
|
+
"showParameterListStep": "whenUnusedParameters"
|
|
72
|
+
},
|
|
73
|
+
"attachments": {
|
|
74
|
+
"enabled": true,
|
|
75
|
+
"tagPrefixes": ["wireframe", "spec"],
|
|
76
|
+
"baseFolder": "specs/attachments"
|
|
77
|
+
},
|
|
78
|
+
"pull": {
|
|
79
|
+
"enableCreatingNewLocalTestCases": false,
|
|
80
|
+
"targetFolder": "specs/pulled"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
"customizations": {
|
|
85
|
+
"fieldDefaults": {
|
|
86
|
+
"enabled": true,
|
|
87
|
+
"defaultValues": {
|
|
88
|
+
"System.State": "Design",
|
|
89
|
+
"Custom.AutomationStatus": "Planned"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"ignoreTestCaseTags": {
|
|
93
|
+
"enabled": true,
|
|
94
|
+
"tags": ["reviewed", "ado-*"]
|
|
95
|
+
},
|
|
96
|
+
"tagTextMapTransformation": {
|
|
97
|
+
"enabled": true,
|
|
98
|
+
"textMap": { "_": " " }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Top-level fields
|
|
107
|
+
|
|
108
|
+
### `orgUrl`
|
|
109
|
+
|
|
110
|
+
Azure DevOps organisation URL. Format: `https://dev.azure.com/YOUR_ORG`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### `project`
|
|
115
|
+
|
|
116
|
+
Azure DevOps project name.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### `configurationKey`
|
|
121
|
+
|
|
122
|
+
*(Optional)* A unique string identifying this config within the ADO project. Used to prevent conflicts when multiple ado-sync configs push into the same Test Plan (e.g. `"smoke-suite"`, `"regression-suite"`). When set, ID writeback tags are namespaced so that one config's tags don't collide with another's.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### `auth`
|
|
127
|
+
|
|
128
|
+
| Field | Description |
|
|
129
|
+
|-------|-------------|
|
|
130
|
+
| `type` | `"pat"` · `"accessToken"` · `"managedIdentity"` |
|
|
131
|
+
| `token` | PAT or access token value. Prefix with `$` to read from an environment variable (e.g. `"$AZURE_DEVOPS_TOKEN"`). |
|
|
132
|
+
| `applicationIdURI` | Required only when `type` is `"managedIdentity"`. |
|
|
133
|
+
|
|
134
|
+
**PAT permissions required:** Test Management (Read & Write), Work Items (Read & Write).
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### `testPlan`
|
|
139
|
+
|
|
140
|
+
| Field | Default | Description |
|
|
141
|
+
|-------|---------|-------------|
|
|
142
|
+
| `id` | *(required)* | ID of the Azure DevOps Test Plan. |
|
|
143
|
+
| `suiteId` | plan root | ID of the Test Suite within the plan. Defaults to the plan's root suite. |
|
|
144
|
+
| `suiteMapping` | `"flat"` | `"flat"` — all TCs go into one suite. `"byFolder"` — folder structure mirrored as nested child suites. |
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### `testPlans` (multi-plan)
|
|
149
|
+
|
|
150
|
+
Use `testPlans` instead of `testPlan` to sync one repo against multiple Test Plans.
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"testPlans": [
|
|
155
|
+
{ "id": 1001, "suiteId": 2001, "include": "specs/smoke/**/*.feature" },
|
|
156
|
+
{ "id": 1002, "suiteId": 2002, "include": "specs/regression/**/*.feature", "suiteMapping": "byFolder" }
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
| Field | Description |
|
|
162
|
+
|-------|-------------|
|
|
163
|
+
| `id` | Test Plan ID |
|
|
164
|
+
| `suiteId` | *(Optional)* Target suite ID |
|
|
165
|
+
| `suiteMapping` | *(Optional)* `"flat"` or `"byFolder"` |
|
|
166
|
+
| `include` | *(Optional)* Override `local.include` for this plan |
|
|
167
|
+
| `exclude` | *(Optional)* Override `local.exclude` for this plan |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### `local`
|
|
172
|
+
|
|
173
|
+
| Field | Default | Description |
|
|
174
|
+
|-------|---------|-------------|
|
|
175
|
+
| `type` | *(required)* | `"gherkin"` · `"markdown"` · `"csv"` · `"excel"` |
|
|
176
|
+
| `include` | *(required)* | Glob pattern(s) relative to the config file. String or array. |
|
|
177
|
+
| `exclude` | *(none)* | Glob pattern(s) to exclude. String or array. |
|
|
178
|
+
| `condition` | *(none)* | Tag expression filter applied before `--tags`. Only scenarios matching this expression are included in sync. e.g. `"@done and not (@ignored or @planned)"` |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `toolSettings`
|
|
183
|
+
|
|
184
|
+
| Field | Default | Description |
|
|
185
|
+
|-------|---------|-------------|
|
|
186
|
+
| `parentConfig` | *(none)* | Relative path to a parent config file. Child values override parent values (deep merge). Circular references are detected and rejected. |
|
|
187
|
+
| `ignoreParentConfig` | `false` | When `true`, the `parentConfig` reference is ignored. Useful to opt a child config out of inheritance temporarily. |
|
|
188
|
+
| `outputLevel` | `"normal"` | `"normal"` — show all results per-line. `"quiet"` — suppress `skipped` lines, show only actionable results. `"verbose"` — reserved for future detailed output. |
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### `sync`
|
|
193
|
+
|
|
194
|
+
| Field | Default | Description |
|
|
195
|
+
|-------|---------|-------------|
|
|
196
|
+
| `tagPrefix` | `"tc"` | Prefix used in ID tags (`@tc:12345`). |
|
|
197
|
+
| `titleField` | `"System.Title"` | Azure DevOps field used as the test case title. |
|
|
198
|
+
| `areaPath` | *(none)* | Area path for newly created Test Cases. |
|
|
199
|
+
| `iterationPath` | *(none)* | Iteration path for newly created Test Cases. |
|
|
200
|
+
| `disableLocalChanges` | `false` | When `true`, no local files are modified (no ID writeback, no pull apply). Use in CI. |
|
|
201
|
+
| `conflictAction` | `"overwrite"` | `"overwrite"` · `"skip"` · `"fail"` — see [Conflict detection](advanced.md#conflict-detection). |
|
|
202
|
+
| `links` | `[]` | Work item link configs — see [Work item linking](spec-formats.md#work-item-linking). |
|
|
203
|
+
| `state` | *(none)* | Set TC State field on change — see [State configuration](advanced.md#state-configuration). |
|
|
204
|
+
| `fieldUpdates` | *(none)* | Custom field update rules — see [Field updates](advanced.md#field-updates). |
|
|
205
|
+
| `format` | *(none)* | TC content formatting options — see [Format configuration](advanced.md#format-configuration). |
|
|
206
|
+
| `attachments` | *(none)* | File attachment sync — see [Attachments](advanced.md#attachments). |
|
|
207
|
+
| `pull` | *(none)* | Pull-specific options — see [Pull configuration](advanced.md#pull-configuration). |
|
|
208
|
+
| `suiteConditions` | *(none)* | Per-tag suite routing rules. |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### `customizations`
|
|
213
|
+
|
|
214
|
+
Controls tag transformations applied before push. See [Customizations](advanced.md#customizations).
|
|
215
|
+
|
|
216
|
+
| Field | Description |
|
|
217
|
+
|-------|-------------|
|
|
218
|
+
| `fieldDefaults` | Default field values applied only on create. |
|
|
219
|
+
| `ignoreTestCaseTags` | Preserve certain Azure-side tags from being removed on push. |
|
|
220
|
+
| `tagTextMapTransformation` | Character/substring replacements applied to tags before push. |
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### `publishTestResults`
|
|
225
|
+
|
|
226
|
+
Configuration for the `publish-test-results` command. See [Publishing test results](publish-test-results.md#configuration).
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## YAML example
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
orgUrl: https://dev.azure.com/my-org
|
|
234
|
+
project: MyProject
|
|
235
|
+
|
|
236
|
+
auth:
|
|
237
|
+
type: pat
|
|
238
|
+
token: $AZURE_DEVOPS_TOKEN
|
|
239
|
+
|
|
240
|
+
testPlan:
|
|
241
|
+
id: 1234
|
|
242
|
+
suiteId: 5678
|
|
243
|
+
suiteMapping: byFolder
|
|
244
|
+
|
|
245
|
+
local:
|
|
246
|
+
type: gherkin
|
|
247
|
+
include: specs/**/*.feature
|
|
248
|
+
exclude:
|
|
249
|
+
- specs/archive/**
|
|
250
|
+
condition: "@done and not @wip"
|
|
251
|
+
|
|
252
|
+
toolSettings:
|
|
253
|
+
outputLevel: quiet
|
|
254
|
+
|
|
255
|
+
sync:
|
|
256
|
+
tagPrefix: tc
|
|
257
|
+
areaPath: "MyProject\\QA Team"
|
|
258
|
+
conflictAction: skip
|
|
259
|
+
links:
|
|
260
|
+
- prefix: story
|
|
261
|
+
relationship: System.LinkTypes.Related
|
|
262
|
+
format:
|
|
263
|
+
prefixTitle: true
|
|
264
|
+
useExpectedResult: false
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Hierarchical config
|
|
270
|
+
|
|
271
|
+
Use `toolSettings.parentConfig` to share common settings across multiple config files.
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
repo/
|
|
275
|
+
ado-sync-base.json ← org, project, auth, shared sync settings
|
|
276
|
+
smoke/
|
|
277
|
+
ado-sync.json ← testPlan.id: 1001, local.include: specs/smoke/**
|
|
278
|
+
regression/
|
|
279
|
+
ado-sync.json ← testPlan.id: 1002, local.include: specs/regression/**
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Child config:
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"toolSettings": { "parentConfig": "../ado-sync-base.json" },
|
|
286
|
+
"testPlan": { "id": 1002, "suiteId": 3001 },
|
|
287
|
+
"local": { "type": "gherkin", "include": "specs/regression/**/*.feature" }
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Child values override parent values using a deep merge (arrays are replaced, not concatenated). Circular references are detected and throw an error.
|
|
292
|
+
|
|
293
|
+
Set `toolSettings.ignoreParentConfig: true` in any child to opt out of inheritance for that config without editing the parent.
|