You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sub-issue of new boards work-item relation umbrella (#271). Hardened spec — do not re-derive decisions. Sibling of #272 (add), #273 (list-type), #274 (remove).
Command Description
List all relations of a single Azure Boards work item. Mirrors az boards work-item relation show. The command fetches the work item with expand='All' and replaces each relation's referenceName with its friendly name, then renders the result as a table or JSON.
The REST surface is Work Items - Get (REST 7.1):
GET https://dev.azure.com/{organization}/_apis/wit/workitems/{id}?$expand=All&api-version=7.1-preview.3
The Python reference implementation is at azure-devops/azext_devops/dev/boards/relations.py:103-106 (show_work_item function) and the table transformer is at azure-devops/azext_devops/dev/boards/_format.py:14-24 (transform_work_item_relations).
The function simply re-uses get_work_item(id, expand='All') and the friendly-name fill (also used by add and remove). The show command is therefore a thin read wrapper.
Locked Decisions
#
Decision
Rationale
1
Org-scoped target.Use: "show [ORGANIZATION/]ID". The work item ID is unique within the organization.
Mirrors az boards work-item relation show. Symmetric with #272, #273, #274.
2
Aliases: []string{"s"}.
Per AGENTS.md show command convention.
3
cobra.ExactArgs(1).
One positional target: the work item ID.
4
Parse the single positional with util.ParseTargetWithDefaultOrganization(ctx, args[0]). scope.Targets[0] is the ID string.
Default output: table with columns TYPE, URL. The TYPE cell is the relation type's friendly name (not referenceName) — friendly-name resolution is performed by the shared helper internal/cmd/boards/workitem/relation/shared/relation.go (introduced by #271).
Vendor verified at vendor/.../v7/workitemtracking/client.go:137, 113.
13
No new mocks needed.
Already generated.
14
No go mod tidy / go mod vendor / scripts/generate_mocks.sh work.
15
No confirmation prompt. The operation is read-only.
Mirrors Python (no confirmation).
16
No progress indicator for a single read operation. The start/stop is still called for symmetry with siblings.
Mirrors siblings.
17
No friendly-name failure is fatal. If a relation's Rel is a referenceName that is not in the list returned by GetRelationTypes (e.g., the type was disabled in the org), the raw referenceName is shown.
Defensive: matches Python's behavior (fill_friendly_name_for_relations_in_work_item does not error on missing mappings).
Command Signature
varshowCmd=&cobra.Command{
Use: "show [ORGANIZATION/]ID",
Aliases: []string{"s"},
Short: "Show relations of a work item.",
Long: heredoc.Doc(` List all relations of a single work item. Each row in the table shows the relation type (friendly name) and the target URL. `),
Args: cobra.ExactArgs(1),
RunE: func(cmd*cobra.Command, args []string) error {
returnrunShow(cmd.Context(), opts, args[0])
},
}
shared.PopulateFriendlyNames mutates populated.Relations in place, replacing each Rel (referenceName) with the friendly Name from GetRelationTypes. It is a best-effort helper introduced by #271 and shared by all three read/write leaves.
JSON Output Contract
Pass the raw *workitemtracking.WorkItem (post GetWorkItem(expand=All)) to opts.exporter.Write. No view struct.
// 1. Fetch the work item with expand=Allexpand:=workitemtracking.WorkItemExpandValues.Allpopulated, _:=wit.GetWorkItem(ctx, workitemtracking.GetWorkItemArgs{Id: &id, Expand: &expand})
// 2. (Inside shared.PopulateFriendlyNames) Resolve referenceNamesrelTypes, _:=wit.GetRelationTypes(ctx, workitemtracking.GetRelationTypesArgs{})
Reference Existing Patterns
internal/cmd/boards/workitem/show (feat: Implement azdo boards work-item show command #238) — sibling for the org-scoped ParseTargetWithDefaultOrganization usage, raw *WorkItem JSON output, and progress indicator lifecycle.
Sub-issue of new
boards work-item relationumbrella (#271). Hardened spec — do not re-derive decisions. Sibling of #272 (add), #273 (list-type), #274 (remove).Command Description
List all relations of a single Azure Boards work item. Mirrors
az boards work-item relation show. The command fetches the work item withexpand='All'and replaces each relation'sreferenceNamewith its friendly name, then renders the result as a table or JSON.The REST surface is Work Items - Get (REST 7.1):
The Python reference implementation is at
azure-devops/azext_devops/dev/boards/relations.py:103-106(show_work_itemfunction) and the table transformer is atazure-devops/azext_devops/dev/boards/_format.py:14-24(transform_work_item_relations).The function simply re-uses
get_work_item(id, expand='All')and the friendly-name fill (also used byaddandremove). Theshowcommand is therefore a thin read wrapper.Locked Decisions
Use: "show [ORGANIZATION/]ID". The work item ID is unique within the organization.az boards work-item relation show. Symmetric with #272, #273, #274.Aliases: []string{"s"}.cobra.ExactArgs(1).util.ParseTargetWithDefaultOrganization(ctx, args[0]).scope.Targets[0]is the ID string.--projectflag. The endpoint is org-scoped.az boards work-item relation show.*WorkItemtoopts.exporter.Write. Do not introduce a view struct.TYPE, URL. TheTYPEcell is the relation type's friendly name (notreferenceName) — friendly-name resolution is performed by the shared helperinternal/cmd/boards/workitem/relation/shared/relation.go(introduced by #271).transform_work_item_relations(_format.py:14-24).relations = nilor empty) renders as an empty table — no error.if result['relations'] is None: return [].--expandflag. All responses useexpand='All'internally. The user gets the full work item with relations populated.--relation-typefilter. The Python always lists all relations; filtering is the caller's job.workitemtracking.Client.{GetWorkItem, GetRelationTypes}.vendor/.../v7/workitemtracking/client.go:137, 113.go mod tidy/go mod vendor/scripts/generate_mocks.shwork.Relis areferenceNamethat is not in the list returned byGetRelationTypes(e.g., the type was disabled in the org), the rawreferenceNameis shown.fill_friendly_name_for_relations_in_work_itemdoes not error on missing mappings).Command Signature
Flags
--id[ORGANIZATION/]ID.--organizationAlso add
util.AddJSONFlags(cmd, &opts.exporter, []string{"id", "rev", "fields", "url", "_links", "relations", "commentVersionRef"}).Code Skeleton (canonical, copy verbatim)
§1.
showOptionsstruct§2.
runShowskeletonshared.PopulateFriendlyNamesmutatespopulated.Relationsin place, replacing eachRel(referenceName) with the friendlyNamefromGetRelationTypes. It is a best-effort helper introduced by #271 and shared by all three read/write leaves.JSON Output Contract
Pass the raw
*workitemtracking.WorkItem(postGetWorkItem(expand=All)) toopts.exporter.Write. No view struct.JSON fields exposed:
id,rev,fields,url,_links,relations,commentVersionRef.Table Output Contract
Use
ctx.Printer("list")with 2 columns:TYPE, URL. Same as #272 (add) and #274 (remove).Command Wiring
internal/cmd/boards/workitem/relation/show/show.gowithpackage show, factoryfunc NewCmd(ctx util.CmdContext) *cobra.Command.import "github.com/tmeckel/azdo-cli/internal/cmd/boards/workitem/relation/show"tointernal/cmd/boards/workitem/relation/relation.go.relation.gowithcmd.AddCommand(show.NewCmd(ctx)).internal/cmd/boards/workitem/relation/shared/relation.go(introduced by Introduceazdo boards work-item relationcommand group #271) —shared.PopulateFriendlyNames.API Surface
Vendored SDK calls (from
vendor/.../v7/workitemtracking/client.go):Reference Existing Patterns
internal/cmd/boards/workitem/show(feat: Implementazdo boards work-item showcommand #238) — sibling for the org-scopedParseTargetWithDefaultOrganizationusage, raw*WorkItemJSON output, and progress indicator lifecycle.internal/cmd/boards/workitem/add(Implementazdo boards work-item relation addcommand #272) — sibling for the table output and friendly-name fill.Reference implementations (for UX parity only):
azure-devops/azext_devops/dev/boards/relations.py:103-106-show_work_itemfunction. Confirms: org-scoped,expand='All', friendly-name fill.azure-devops/azext_devops/dev/boards/_format.py:14-24-transform_work_item_relationsconfirms table columnsRelation Type, URL.expand: relationsparameter on the read tool is the closest equivalent.TDD Test Plan
TestNewCmd_showUse == "show [ORGANIZATION/]ID",Aliases == ["s"],Args == cobra.ExactArgs(1).Test_runShow_minimalTYPEcells are the friendly names.Test_runShow_noRelationsrelations = nil.Test_runShow_invalidSourceID"abc".util.FlagErrorfwith"work item ID must be a positive integer". SDK is not called.Test_runShow_zeroSourceID"0".util.FlagErrorf. SDK is not called.Test_runShow_negativeSourceID"-5".util.FlagErrorf. SDK is not called.Test_runShow_orgScopeOnly"1234".args.Id == ptr(1234), scope.Organization is the default.Test_runShow_explicitOrg"myorg/1234".args.Id == ptr(1234), scope.Organization is"myorg".Test_runShow_APIErrorGetWorkItemreturnserrors.New("boom").Test_runShow_success_JSON--jsonflag set.*WorkItem.Test_runShow_tableOutputTYPEcells match the friendly names returned byGetRelationTypes.Test_runShow_unknownRelationTypeRel = "Custom.Unmapped".TYPEcell renders"Custom.Unmapped"(rawreferenceName); no error.References
vendor/.../v7/workitemtracking/client.go:113 (GetRelationTypes), 137 (GetWorkItem).vendor/.../v7/workitemtracking/models.go:1425 (WorkItemRelation), :1435 (WorkItemRelationType).internal/mocks/workitemtracking_client_mock.go:669 (GetRelationTypes), 849 (GetWorkItem).internal/azdo/factory.go:149—ClientFactory().WorkItemTracking(ctx, organization).7.1-preview.3).boards work-item relationsubgroup (Introduceazdo boards work-item relationcommand group #271). Sibling: Implementazdo boards work-item relation addcommand #272, Implementazdo boards work-item relation list-typecommand #273, Implementazdo boards work-item relation removecommand #274.internal/cmd/boards/workitem/show(feat: Implementazdo boards work-item showcommand #238),internal/cmd/boards/workitem/add(Implementazdo boards work-item relation addcommand #272).