Implementing a Go CLI for Managing Azure DevOps

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating the CLI
  5. Connecting to Azure DevOps
  6. Managing Work Items
  7. Conclusion

Introduction

In this tutorial, we will learn how to create a Command-Line Interface (CLI) tool using Go (Golang) for managing Azure DevOps. Azure DevOps provides a set of services for development teams to plan, develop, test, and deliver applications efficiently. By the end of this tutorial, you will be able to perform various tasks related to work items in Azure DevOps through a CLI created with Go.

Prerequisites

To follow along with this tutorial, you will need:

  • Go installed on your machine
  • An Azure DevOps account

Setup

Before we begin coding, let’s set up our project and install any necessary dependencies.

  1. Create a new directory for your project:

    ```shell
    mkdir go-azure-devops-cli
    cd go-azure-devops-cli
    ```
    
  2. Initialize the project and create a go.mod file:

    ```shell
    go mod init github.com/your-username/go-azure-devops-cli
    ```
    
  3. Install the github.com/microsoft/azure-devops-go-api package, which provides Go bindings for the Azure DevOps API:

    ```shell
    go get github.com/microsoft/azure-devops-go-api/azuredevops
    ```
    

Creating the CLI

Now that our project is set up, let’s start implementing our CLI.

  1. Create a new Go file named main.go:

    ```shell
    touch main.go
    ```
    
  2. Open main.go in an editor and add the following code:

    ```go
    package main
    
    import (
        "fmt"
        "os"
    
        "github.com/microsoft/azure-devops-go-api/azuredevops"
    )
    
    func main() {
        // Check if command-line arguments are provided
        if len(os.Args) < 2 {
            fmt.Println("Usage: go-azure-devops-cli <command>")
            os.Exit(1)
        }
    
        // Parse the command
        command := os.Args[1]
    
        // Perform the corresponding action based on the command
        switch command {
        case "connect":
            connectToAzureDevOps()
        case "workitems":
            manageWorkItems()
        default:
            fmt.Println("Unknown command")
        }
    }
    ```
    
    In this code, we import the necessary packages, define the `main` function, and check if any command-line arguments are provided. Depending on the command, we will call different functions to perform the corresponding actions.
    

Connecting to Azure DevOps

To use the Azure DevOps API, we need to authenticate and establish a connection with the service.

  1. Add the following code below the main function in main.go:

    ```go
    func connectToAzureDevOps() {
        personalAccessToken := "<YOUR_PERSONAL_ACCESS_TOKEN>"
        organizationURL := "<YOUR_ORGANIZATION_URL>"
    
        connection := azuredevops.NewPatConnection(organizationURL, personalAccessToken)
        client, _ := connection.GetClient()
    
        // Test the connection
        me, _ := client.GetMyProfile(nil)
        fmt.Printf("Connected to Azure DevOps as %s\n", *me.DisplayName)
    }
    ```
    
    Replace `<YOUR_PERSONAL_ACCESS_TOKEN>` with your personal access token from Azure DevOps, and `<YOUR_ORGANIZATION_URL>` with the URL of your Azure DevOps organization.
    
    In this code, we create a connection using our personal access token and organization URL. We then retrieve the client to interact with the Azure DevOps API. Finally, we test the connection by getting the profile of the authenticated user.
    
  2. Let’s test the connection functionality by adding the following code snippet at the end of the main function in main.go:

    ```go
    // Test connection command
    case "test":
        connectToAzureDevOps()
    ```
    
    Save the file and run the CLI with the `test` command:
    
    ```shell
    go run main.go test
    ```
    
    If everything is set up correctly, you should see a message indicating a successful connection to Azure DevOps.
    

Managing Work Items

Now that we can connect to Azure DevOps, let’s add functionality to manage work items.

  1. Add the following code below the connectToAzureDevOps function in main.go:

    ```go
    func manageWorkItems() {
        personalAccessToken := "<YOUR_PERSONAL_ACCESS_TOKEN>"
        organizationURL := "<YOUR_ORGANIZATION_URL>"
        project := "<YOUR_PROJECT_NAME>"
    
        connection := azuredevops.NewPatConnection(organizationURL, personalAccessToken)
        client, _ := connection.GetClient()
    
        // Get a list of work items
        workItems, _ := client.GetWorkItems(context.Background(), azuredevops.GetWorkItemsArgs{
            Project:         &project,
            ItemIds:         &[]int{1, 2, 3}, // Replace with the desired work item IDs
            Fields:          &[]string{"System.Title", "System.State"},
            AsOf:            nil,
            Expand:          nil,
            ErrorPolicy:     nil,
            $top:            nil,
            IncludeIdentity: nil,
        })
    
        fmt.Println("Work Items:")
        for _, workItem := range *workItems {
            fmt.Printf("- ID: %d, Title: %s, State: %s\n", *workItem.Id, *workItem.Fields["System.Title"], *workItem.Fields["System.State"])
        }
    }
    ```
    
    Replace `<YOUR_PERSONAL_ACCESS_TOKEN>`, `<YOUR_ORGANIZATION_URL>`, and `<YOUR_PROJECT_NAME>` with your own values. Additionally, you can replace the `ItemIds` array with the IDs of specific work items you want to retrieve. The fields `System.Title` and `System.State` are specified in the `Fields` array to retrieve only those values.
    
    In this code, we retrieve a list of work items based on the given parameters and print their IDs, titles, and states.
    
  2. Let’s test the work items functionality by adding the following code snippet at the end of the main function in main.go:

    ```go
    // Work items command
    case "workitems":
        manageWorkItems()
    ```
    
    Save the file and run the CLI with the `workitems` command:
    
    ```shell
    go run main.go workitems
    ```
    
    If everything is set up correctly, you should see a list of work items retrieved from Azure DevOps.
    

Conclusion

In this tutorial, we learned how to create a Go CLI for managing Azure DevOps. We covered the basics of setting up a Go project, establishing a connection to Azure DevOps, and retrieving work items. You can extend this CLI by adding more commands and functionality to perform actions like creating new work items, updating existing ones, managing pull requests, and more.

Remember to secure your personal access token and handle error scenarios appropriately in a production-ready CLI tool.

With the knowledge gained from this tutorial, you can now explore and build powerful automation and management tools for Azure DevOps using Go. Happy coding!