Skip to content

feat: Introduce azdo pipelines build command group #213

@tmeckel

Description

@tmeckel

Introduce a new build subgroup under the existing azdo pipelines command group (umbrella tracked in #116). The build subgroup is a thin router: it has no leaf commands of its own at the moment — it registers the list leaf (tracked in #211) and serves as the natural home for future legacy-Build-API commands (e.g. show, queue, cancel) and nested definition and tag subgroups.

The build subgroup surfaces the legacy Azure DevOps Build API surface (the az pipelines build group from the Azure CLI). It is distinct from the runs subgroup (#214), which surfaces the modern Azure Pipelines API surface (the az pipelines runs group). Both subgroups share the same vendored SDK client (build.Client) — the split is purely CLI ergonomics to match the Azure CLI's terminology and Python extension's command group registration.

Implementation Notes

  • The build subgroup has no behavior of its own. Its sole responsibility is to register child leaf commands via cmd.AddCommand(...).
  • The first child is azdo pipelines build list (tracked in feat: Implement azdo pipelines build list command #211). Future children follow the same leaf issue template.
  • No new SDK client is required — build.Client is already wired in internal/azdo/connection.go:50-51 (interface) and internal/azdo/factory.go:61 (impl). No new mocks are required — MockBuildClient.GetBuilds and MockBuildClient.QueueBuild (and any other future Build methods) are already present.
  • No new shared helpers are required for this parent. Future shared logic across multiple build leaves (e.g. a common runTableRow helper) may be extracted into this package's build.go or a separate internal/cmd/pipelines/build/shared package — do not pre-extract.
  • The Use: line should be build (no description on the Use line itself; the Short and Long fields provide description text).
  • Aliases are not provided on group commands; only on leaf commands.

Command Wiring

  1. Create internal/cmd/pipelines/build/build.go:
package build

import (
	"github.com/spf13/cobra"

	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build/cancel"
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build/list"
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build/queue"
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build/show"
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build/tag"  // new in #276
	"github.com/tmeckel/azdo-cli/internal/cmd/util"
)

func NewCmd(ctx util.CmdContext) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "build",
		Short: "Manage legacy Azure DevOps Build API resources.",
		Long: `Surface for the legacy Azure DevOps Build API.

Mirrors the 'az pipelines build' group from the Azure CLI. Routes to child
commands that operate on the Build REST API (builds, definitions, queues).`,
	}

	cmd.AddCommand(list.NewCmd(ctx))
	cmd.AddCommand(show.NewCmd(ctx))
	cmd.AddCommand(cancel.NewCmd(ctx))   // new in #252
	cmd.AddCommand(queue.NewCmd(ctx))    // new in #253
	cmd.AddCommand(tag.NewCmd(ctx))      // new in #276
	return cmd
}
  1. Register the new subgroup in the existing umbrella at internal/cmd/pipelines/pipelines.go:
import (
	// ... existing imports ...
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/build"
	"github.com/tmeckel/azdo-cli/internal/cmd/pipelines/runs"
	// ...
)

func NewCmd(ctx util.CmdContext) *cobra.Command {
	cmd := &cobra.Command{ /* ... existing ... */ }
	cmd.AddCommand(variablegroup.NewCmd(ctx))
	cmd.AddCommand(variable.NewCmd(ctx))
	cmd.AddCommand(build.NewCmd(ctx))     // new in #213
	cmd.AddCommand(runs.NewCmd(ctx))      // new in #214
	return cmd
}
  1. No change is required to internal/cmd/root/root.go (the pipelines group is already registered).

SDK / Client Requirements

  • Client: build.Client (vendored, already wired).
    • Interface: internal/azdo/connection.go:50-51Build(ctx context.Context, organization string) (build.Client, error).
    • Factory: internal/azdo/factory.go:61 — constructs the client from the connection.
    • Mock: internal/mocks/build_client_mock.go — full mock implementing build.Client; GetBuilds is at lines 701-714, UpdateBuild at line 1286, QueueBuild at line 1227, GetDefinitions at line 837, AddBuildTag at line 46, AddBuildTags at line 61, DeleteBuildTag at line 210, GetBuildTags at line ~700.
  • No new vendored packages required. vendor/github.com/microsoft/azure-devops-go-api/azuredevops/v7/build/ is already present.
  • No new mocks required for the parent itself or for any of the new leaves (feat: Implement azdo pipelines build cancel command #252, feat: Implement azdo pipelines build queue command #253, Introduce azdo pipelines build tag command group #276). All methods needed are already mocked.
  • No go mod tidy / go mod vendor / scripts/generate_mocks.sh work required for this parent or for any of its sub-issues.

Subgroup Wiring

  • The build subgroup also exposes nested subgroups: a tag subgroup (introduced by Introduce azdo pipelines build tag command group #276) and a planned definition subgroup (not yet filed).
  • Update internal/cmd/pipelines/build/build.go to call cmd.AddCommand(tag.NewCmd(ctx)) once the tag subgroup is implemented.

Sub-Issues

Each new leaf will be filed as a follow-up issue using the same canonical 12-section body format. When filed, the issue number will replace the placeholder in the checklist above.

Tooling & Validation

  • go build ./... is clean.
  • go test ./internal/cmd/pipelines/build/... passes.
  • go run cmd/azdo/azdo.go pipelines build --help renders the subgroup's short and long descriptions and lists list, show, cancel, queue, and tag as children.
  • go run cmd/azdo/azdo.go pipelines --help shows build alongside variable-group and variable.
  • make lint passes (golangci-lint, per .golangci.yml).
  • make docs regenerates docs/pipelines_build.md with the new subgroup.

References

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions