Skip to content

feat: Implement azdo pipelines build tag list command #279

@tmeckel

Description

@tmeckel

Sub-issue of #276. Hardened spec — do not re-derive decisions. Mirrors az pipelines build tag list from the Azure CLI and the Python implementation at azure-dev-ops/azext_devops/dev/pipelines/build.py#L210-L218.

Command Description

List the tags currently attached to an Azure Pipelines build identified by its numeric build ID. The command returns a *[]string (the list of tag name strings). The output is a single-column table Tags, one row per tag.

GET https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}/tags?api-version=7.1-preview.3

Locked Decisions (do not re-derive)

# Decision Rationale
1 Use the vendored SDK method build.Client.GetBuildTags. Mock already generated at internal/mocks/build_client_mock.go. Mandate: vendored API.
2 The build is identified by a positional BUILD argument ([ORGANIZATION/]PROJECT/BUILD). The BUILD segment must parse as a positive integer (no name resolution). Mirrors cancel (#252) and queue (#253).
3 Parse the positional using util.ParseProjectTargetWithDefaultOrganization from internal/cmd/util/scope.go:183. The function returns a *Target with Organization, Project, Target fields, accepting 2- or 3-segment inputs. Mirrors internal/cmd/pipelines/build/{cancel,queue}/ precedent.
4 The user is not required to pass a project; the project segment in the positional is optional. When omitted, the project is resolved from the default config. Mirrors all other pipelines build leaves.
5 No additional flags beyond --json / --jq / --template. The build ID is the only input. Mirrors az pipelines build tag list which is flagless aside from the build identifier.
6 Default output is a table. JSON output via --json passes the raw SDK result *[]string to opts.exporter.Write. No view struct needed for a list of strings; mirrors the show-sibling convention.
7 A build with no tags returns an empty *[]string; the table emits zero rows; JSON emits []. No error. Mirrors az pipelines build tag list behavior.
8 No --max-items cap. Build tag lists are short (typically < 20 entries) and the SDK does not paginate. Mirrors az pipelines build tag list.
9 No new SDK client, no new helper, no new package beyond internal/cmd/pipelines/build/tag/list. Mandate: minimal code.
10 Mock for GetBuildTags is already generated. Do not regenerate. Verified at internal/mocks/build_client_mock.go.

Command Signature

azdo pipelines build tag list [ORGANIZATION/]PROJECT/BUILD
  [--json ...]
  • cobra.ExactArgs(1)args[0] → target (via util.ParseProjectTargetWithDefaultOrganization).
  • The Target field is parsed as int; non-numeric / zero / negative values rejected with util.FlagErrorf.

Flags

Flag Maps to Notes
--json / --jq / --template util.AddJSONFlags JSON export

JSON Output Contract

Pass the raw SDK result *[]string to opts.exporter.Write. The result is a list of tag name strings. No view struct is required.

Caveat: the SDK returns *[]string (a pointer to a slice of strings). The exporter handles both nil and empty-slice cases by emitting null and [] respectively.

Table Output Contract

Mirrors transform_build_tags_output from _format.py (single column Tags). One row per tag in the SDK response. The table header is Tags (uppercase, single column).

Tags
release
nightly
v1.2.3

An empty SDK result produces a table with no rows (only the header).

Command Wiring

  • Package path: internal/cmd/pipelines/build/tag/list
  • Files:
    • list.goNewCmd(ctx util.CmdContext) *cobra.Command + listOptions + runList. Cobra Use: "list [ORGANIZATION/]PROJECT/BUILD". Aliases: []string{"ls", "l"} to match the project convention.
    • list_test.go — table-driven gomock tests
  • Update internal/cmd/pipelines/build/tag/tag.go to add list.NewCmd(ctx) to cmd.AddCommand(...). Update the Example block.
  • Higher-level parents must already remain wired: pipelinesbuildtaglist.

API Surface

Reuse the already-vendored client. No new SDK clients or mocks required.

  • build.Client.GetBuildTagsTags - Get (REST 7.1-preview.3)
  • build.GetBuildTagsArgs struct: {Project *string, BuildId *int}.
  • The method returns *[]string (the list of tag name strings).

Mock for GetBuildTags is already generated. No mock regeneration needed.

Reference Existing Patterns

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions