Agent skill
sync-ado-repos
Sync GitHub repos from bluebillywig org to an ADO "Repository" picklist field on all work item types
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/sync-ado-repos
SKILL.md
Sync GitHub Repos to ADO Picklist
Fetches all repos from github.com/bluebillywig and creates/updates a Custom.Repository picklist field on all work item types across all inherited processes in Azure DevOps.
Process
Write and execute a Node.js script (temp file, delete after). Use built-in fetch (Node 18+).
Auth headers:
- GitHub:
Authorization: Bearer {GITHUB_TOKEN} - ADO:
Authorization: Basic {base64(':' + ADO_PAT)}
ADO API version: 7.1 for all calls except field creation (4.1-preview.1) and project properties (7.1-preview.1).
1. Read credentials from .env
Parse C:\dev\ai\orch\.env for ADO_ORG, ADO_PAT, GITHUB_TOKEN. Use fs.readFileSync with line parsing (split on =, trim, strip quotes). Last value wins for duplicate keys.
2. Fetch all repos from github.com/bluebillywig
GET https://api.github.com/orgs/bluebillywig/repos?per_page=100&page=N
Paginate until empty page. Extract .name, sort alphabetically, log count.
3. Find or create/update picklist
First check if Custom.Repository field exists and read its picklistId:
GET https://dev.azure.com/{org}/_apis/wit/fields/Custom.Repository?api-version=7.1
If no picklist ID from field, search all picklists for one named "Repository":
GET https://dev.azure.com/{org}/_apis/work/processes/lists?api-version=7.1
Create (if not found -- include name!):
POST .../lists?api-version=7.1
Body: { "name": "Repository", "type": "String", "items": [...repos], "isSuggested": true }
Update (if found):
PUT .../lists/{listId}?api-version=7.1
Body: { "id": "{listId}", "items": [...repos], "isSuggested": true }
4. Get all inherited processes and their WITs
GET https://dev.azure.com/{org}/_apis/work/processes?$expand=projects&api-version=7.1
Filter to customizationType === 'inherited'. The $expand=projects parameter includes which projects use each process. For EACH inherited process, fetch WITs:
GET https://dev.azure.com/{org}/_apis/work/processes/{processId}/workitemtypes?api-version=7.1
5. Create field if it doesn't exist
If step 3's field check returned 404, create the field. Use the older processdefinitions API with type: "string" (NOT "picklistString"):
POST https://dev.azure.com/{org}/_apis/work/processdefinitions/{processId}/fields?api-version=4.1-preview.1
Body: { "name": "Repository", "type": "string", "pickList": { "id": "{picklistId}" } }
The type must be "string" — the picklist binding is what makes it a picklist field. Using "picklistString" causes FieldTypeInvalid.
6. Add field to all work item types
For each WIT, check wit.customization:
If customization !== 'system' (already derived/custom): add field directly:
POST .../processes/{processId}/workItemTypes/{witRefName}/fields?api-version=7.1
Body: { "referenceName": "Custom.Repository" }
If customization === 'system' (not yet derived): skip — the REST API cannot derive a WIT with the same name as the system parent. These require manual derivation via the ADO UI.
- Ignore 409 (field already added)
- Skip Test Case/Test Plan/Test Suite — system-only types that don't accept custom fields
7. Add control to form layout (CRITICAL)
Adding a field to a WIT does NOT make it visible on the form. You must also add a control to the WIT's layout.
For each WIT where the field was added:
- Get the layout:
GET .../processes/{processId}/workItemTypes/{witRefName}/layout?api-version=7.1
-
Check if
Custom.Repositorycontrol already exists (scan all pages/sections/groups/controls forctrl.id === 'Custom.Repository'). -
Find a suitable group on the "Details" page. Prefer groups labeled "Details" or "Classification". Avoid groups that already contain an
HtmlFieldControl— ADO allows only one HTML control per group (error VS403105). -
If the first group fails with 500 (HTML control conflict), find another group without HTML controls.
-
If an existing plain control exists, remove it first:
DELETE .../processes/{processId}/workItemTypes/{witRefName}/layout/groups/{groupId}/controls/Custom.Repository?api-version=7.1
- Add the control as a multivalue contribution (same pattern as
Custom.BusinessUnit/ "Business Unit(s)"). This uses the already-installedms-devlabs.vsts-extensions-multivalue-controlextension:
POST .../processes/{processId}/workItemTypes/{witRefName}/layout/groups/{groupId}/controls?api-version=7.1
Body: {
"id": "Custom.Repository",
"label": "Repository",
"visible": true,
"readOnly": false,
"isContribution": true,
"contribution": {
"contributionId": "ms-devlabs.vsts-extensions-multivalue-control.multivalue-form-control",
"inputs": { "FieldName": "Custom.Repository" }
}
}
8. Report
Output markdown summary: repos synced, picklist created vs updated, processes and WITs updated vs skipped, controls added to layout. Include reminder to install Multivalue control extension for multi-select.
Known Limitations
- System WITs (
customization: system): cannot add fields or layout controls via API. Open ADO UI > Process > click the WIT to auto-derive, then re-run. - Test Case/Plan/Suite: locked system types across all processes, skip these.
- Field type: must use
"string"(not"picklistString") in theprocessdefinitionsAPI. - HTML control conflict: each layout group allows only one HTML control. If a group already has one, pick a different group.
- Picklist creation: must include
namefield in POST body or API returns 400. - Multivalue extension:
ms-devlabs.vsts-extensions-multivalue-controlis already installed in the org. The field type is identical to a regular picklist string — multi-select is purely a layout control concern (useisContribution: truewith the extension'scontributionId). - isSuggested must be true: The multivalue control stores values as semicolons-separated (e.g.,
foo;bar). IfisSuggested: false, ADO validates the combined string against individual picklist items and rejects it. UseisSuggested: trueso values are suggestions, not enforced.
Important Notes
- Handle errors gracefully -- if one WIT rejects the field, log and continue
- Run with
node.exedirectly to avoid Git Bash shell issues - Delete temp script after execution
Verification
- ADO > Project Settings > Process > Work item type -- verify "Repository" field exists
- Open a work item -- confirm repo dropdown shows all bluebillywig repos
- If multi-select needed: install Multivalue control extension
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?