Azure DevOps extension that renders the full dependency chain for any Test Case, Bug, or Change Request — as a collapsible list or an interactive graph, inside the work item form and in a dedicated Boards hub. Configurable per-user and org-wide, with CSV/text export.
Version history
See CHANGELOG.md for the full release history.
Project structure
ado-predecessor-tree/
├── src/
│ ├── config.ts # Config schema, defaults, persistence (per-user + org)
│ ├── treeService.ts # API fetching + tree building (config-driven)
│ ├── exporters.ts # CSV download + copy-as-text
│ ├── TreeExplorer.tsx # Toolbar, stats, search, list view, view switch
│ ├── GraphView.tsx # Layered SVG dependency graph
│ ├── SettingsPanel.tsx # Config editor (apply / save org default)
│ ├── TreeView.css # Styles (shared by all views)
│ ├── hub/
│ │ ├── hub.html # HTML template for hub page
│ │ └── index.tsx # Hub app entry point
│ └── form-panel/
│ ├── form-panel.html # HTML template for form panel
│ └── index.tsx # Form panel entry point
├── images/
│ ├── icon.png # 128×128 extension icon
│ └── screenshot-*.png # Marketplace screenshots (list, graph, form, settings, nav)
├── dist/ # Built output (generated by webpack)
├── vss-extension.json # Extension manifest
├── webpack.config.js
├── tsconfig.json
├── package.json
├── overview.md # Marketplace listing description
└── LICENSE.md
Note: there is no longer a
TreeView.tsx— it was replaced byTreeExplorer.tsx. TheTreeView.cssfile remains and is still used.
One-time setup
1. Prerequisites
- Node.js 18+
tfx-cli(installed as a dev dependency — no global install needed)
2. Create a Visual Studio Marketplace publisher
- Go to https://marketplace.visualstudio.com/manage
- Sign in with your Microsoft account
- Click Create publisher
- Choose a publisher ID (e.g.
nirusha-tools) — this is permanent and public - Fill in display name and optionally a logo
3. Update the manifest
In vss-extension.json, replace:
"publisher": "NirushaD"→ your actual publisher ID"NirushaD"in links → your GitHub username/org
4. Create a Personal Access Token for publishing
- In Azure DevOps, go to User Settings → Personal Access Tokens
- Create a new token with:
- Organisation: All accessible organisations
- Scopes:
Marketplace (Publish)
- Copy the token — you will use it as
MARKETPLACE_PAT
Build
npm install
npm run build
Output lands in ./dist/.
Icons and screenshots
The marketplace listing uses a 128×128 PNG at images/icon.png and the
images/screenshot-*.png files referenced from overview.md (list view, graph
view, work item form panel, settings panel, and Boards navigation). If you update
a screenshot, keep the filename and it flows through to the listing on the next
publish.
Package
npm run package
This produces ./release/NirushaD.predecessor-tree-viewer-1.0.0.vsix.
Publish
Option A — Command line
MARKETPLACE_PAT=<your-token> npm run publish
Option B — Marketplace UI
- Go to https://marketplace.visualstudio.com/manage
- Click New extension → Azure DevOps
- Upload the
.vsixfile from./release/
First publish is PRIVATE by default
Your extension starts as Private. To make it public:
- Go to your publisher page on the Marketplace
- Click the extension → Share/Publish
- Select Make public
Microsoft performs a light review before public extensions are visible to all ADO users (typically 1–3 business days for new publishers).
Install on your own organisation (while private)
- On the Marketplace page for your extension, click Share
- Enter your ADO organisation name
- In your ADO org: Organisation Settings → Extensions → Browse marketplace
- Search for your extension by name and install it
Local development / testing
You can test against a real ADO org without publishing using tfx:
# Publish to your org directly (private, no marketplace)
npx tfx extension publish \
--manifest-globs vss-extension.json \
--token <your-PAT> \
--share-with <your-org-name>
Then install from Organisation Settings → Extensions.
Bumping the version for updates
- Increment
"version"invss-extension.json(semver:1.0.0→1.0.1) - Run
npm run packageandnpm run publish
ADO organisations that have installed your extension will receive the update automatically.
Configuration
All behaviour that used to be hardcoded now lives in src/config.ts as DEFAULT_CONFIG, and every field is editable at runtime from the in-app Settings panel (the ⚙ button in the toolbar).
| Setting | What it controls | Default |
|---|---|---|
| Work item types to include | Only these types appear in the tree | Bug, Defect, Change Request |
| Test case type | Roots of this type follow Tests / Tested By links | Test Case |
| Hidden states | Items in these states are hidden by default (toggleable) | Closed |
| Relations to follow from the root | Which links to follow at level 0 (descendants always follow Predecessor) | Predecessor |
| Severity field | Reference name of the severity field | Microsoft.VSTS.Common.Severity |
| Extra columns | Additional fields shown inline and in exports | none |
| Maximum depth | Safety cap on recursion | 20 |
Per-user vs organisation defaults
Settings persist through ADO's Extension Data Service:
- Apply for me → stored at
Userscope; affects only the current user. - Save as org default → stored at
Defaultscope; becomes the baseline for everyone in the organisation. Requires the acting user to have permission to write extension data (typically a collection/organisation admin).
Effective config is resolved as: DEFAULT_CONFIG ← org default ← (view preferences are separate and always per-user). If persistence is unavailable for any reason, the extension silently falls back to DEFAULT_CONFIG so the tree always renders.
View preferences (list/graph, show-closed, expand depth) are always per-user and saved automatically as you change them.
How the tree is built
-
BFS collection (
collectItemsByBFS) walks outward from the root usinggetWorkItemsBatchwith$expand: relations. From the root it follows the configured root relations; below the root it follows Predecessor only. It collects the full reachable graph regardless of state, so the show/hide-Closed toggle is instant and needs no re-fetch.ADO API constraint:
getWorkItemsBatchcannot combine$expand: relationswith an explicitfieldslist — relations come back empty. The code omitsfieldsand lets the relations expand return the full field set. -
Tree construction (
buildNode) shapes the cached items into a tree, filtering to the configured types, labelling each link, and flagging excluded-state and duplicate (cycle) nodes. Closed items are flagged, not dropped — the UI hides them based on the toggle. -
Views consume the same
TreeNode:TreeExplorerrenders the list, toolbar, search, and stats.GraphViewcollapses repeated IDs into unique nodes and rings any node with in-degree > 1 (a shared blocker).
Extending
Add a new relation category
In src/config.ts, add a key to RelationKey, its raw ADO rel string to REL_STRING, and a label to REL_LABEL. It then appears automatically as a checkbox in the Settings panel's "Relations to follow from the root".
Restrict the form panel to certain work item types
Add a filter to the form contribution in vss-extension.json:
"properties": {
"name": "Dependency Tree",
"uri": "dist/form-panel.html",
"height": 400,
"filter": { "workItemTypes": ["Test Case", "Bug", "Change Request"] }
}
Adjust the CSV schema
exportCsv in src/exporters.ts flattens the tree to rows. The column set mirrors the indented CSV produced by the daily PowerShell extract; add or reorder columns there.
Add a column from a custom field
No code change needed — open Settings → Extra columns, give it a label and the field's reference name (e.g. Custom.FunctionGroup), and Apply.
Policies
- Privacy policy — no telemetry, no external services; read-only access to your own organisation's APIs.
- Support policy — how to report issues and what to expect.
- License — MIT.
- Changelog