Back

Step by Step Guide to Building an Azure DevOps API Integration in Go

Aug 2, 20247 minute read

Introduction

Hey there, fellow developer! Ready to dive into the world of Azure DevOps API integration using Go? You're in for a treat. We'll be using the azure-devops-go-api package to make our lives easier. This powerful API opens up a world of possibilities for automating and extending your Azure DevOps workflows. Let's get started!

Prerequisites

Before we jump in, make sure you've got:

  • Go installed on your machine (I know you probably do, but just checking!)
  • An Azure DevOps account and a Personal Access Token (PAT)

Got those? Great! Let's move on.

Setting up the project

First things first, let's set up our Go module and grab the azure-devops-go-api package:

mkdir azure-devops-integration && cd azure-devops-integration go mod init azure-devops-integration go get github.com/microsoft/azure-devops-go-api/azuredevops

Configuring the Azure DevOps client

Now, let's get our hands dirty with some code. We'll start by setting up our Azure DevOps client:

package main import ( "github.com/microsoft/azure-devops-go-api/azuredevops" "github.com/microsoft/azure-devops-go-api/azuredevops/core" ) func main() { organizationUrl := "https://dev.azure.com/your-organization" personalAccessToken := "your-pat-here" connection := azuredevops.NewPatConnection(organizationUrl, personalAccessToken) client := core.NewClient(connection) // We're all set to start making API calls! }

Basic API operations

Let's start with some basic operations to get our feet wet:

Fetching projects

projects, err := client.GetProjects(context.Background(), core.GetProjectsArgs{}) if err != nil { log.Fatal(err) } for _, project := range projects.Value { fmt.Printf("Project: %s\n", *project.Name) }

Retrieving work items

workitem := workitemtracking.NewClient(connection) item, err := workitem.GetWorkItem(context.Background(), workitemtracking.GetWorkItemArgs{ Id: 1, // Replace with your work item ID }) if err != nil { log.Fatal(err) } fmt.Printf("Work Item Title: %s\n", *item.Fields["System.Title"])

Creating a new work item

newWorkItem := []workitemtracking.JsonPatchOperation{ { Op: &workitemtracking.OperationValues.Add, Path: converter.String("/fields/System.Title"), Value: "New task created via Go API", }, } createdItem, err := workitem.CreateWorkItem( context.Background(), workitemtracking.CreateWorkItemArgs{ Type: "Task", Project: "Your Project Name", Document: &newWorkItem, }, ) if err != nil { log.Fatal(err) } fmt.Printf("Created Work Item ID: %d\n", *createdItem.Id)

Advanced operations

Ready to level up? Let's tackle some more complex operations:

Querying work items

query := "Select [System.Id], [System.Title] From WorkItems Where [System.WorkItemType] = 'Bug' AND [System.State] = 'Active'" queryResults, err := workitem.QueryByWiql(context.Background(), workitemtracking.QueryByWiqlArgs{ Wiql: &workitemtracking.Wiql{Query: &query}, }) if err != nil { log.Fatal(err) } for _, item := range queryResults.WorkItems { fmt.Printf("Work Item ID: %d\n", *item.Id) }

Updating work items

updateOperations := []workitemtracking.JsonPatchOperation{ { Op: &workitemtracking.OperationValues.Add, Path: converter.String("/fields/System.State"), Value: "Resolved", }, } updatedItem, err := workitem.UpdateWorkItem( context.Background(), workitemtracking.UpdateWorkItemArgs{ Id: 1, // Replace with your work item ID Document: &updateOperations, }, ) if err != nil { log.Fatal(err) } fmt.Printf("Updated Work Item State: %s\n", *updatedItem.Fields["System.State"])

Error handling and best practices

Always check for errors after API calls. It's a Go best practice, and it'll save you headaches later. Also, be mindful of rate limits. If you're making lots of requests, consider implementing some form of throttling.

Testing the integration

Don't forget to write tests! Here's a quick example of how you might test your integration:

func TestGetProjects(t *testing.T) { // Mock the API response httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder("GET", "https://dev.azure.com/your-organization/_apis/projects", httpmock.NewStringResponder(200, `{"count":1,"value":[{"id":"project-id","name":"Test Project"}]}`)) // Run your GetProjects function projects, err := GetProjects() assert.NoError(t, err) assert.Equal(t, 1, len(projects)) assert.Equal(t, "Test Project", projects[0].Name) }

Conclusion

And there you have it! You've just built a solid Azure DevOps API integration using Go. You've learned how to set up the client, perform basic and advanced operations, handle errors, and even test your integration.

Remember, this is just scratching the surface. The Azure DevOps API is vast and powerful, so don't be afraid to explore further. Check out the official documentation for more endpoints and operations.

Now go forth and automate all the things! Happy coding!