skip to Main Content

I’m writing an Azure DevOps extension using the azure-devops-extension-sdk in React.js. I’m trying to query our existing Product Backlog Items for one with a matching title to get the id for that PBI and update the description as I add new tasks to it.

Is this something that’s possible in the Azure DevOps Extension SDK or do I need to import a different library for this interface?

I can’t seem to find any documentation on how to authenticate and interface with Azure DevOps Services API. I haven’t found much in regards to authentication. I’ve found documentation on what endpoint to use to run my WIQL query and how to format the payload, but I can’t find the SDK methods to accomplish those requests.

This documentation points back to the VSS Web Extension SDK, not the current Azure DevOps Extension SDK.
https://learn.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-7.2&viewFallbackFrom=azure-devops-rest-7.0

Other documentation refers to utilizing C#, but extensions are written utilizing React.js and TypeScript.

2

Answers


  1. Indeed, that document still uses the legacy Visual Studio Teams Service Web Extension SDK.

    In addition to the Azure DevOps Web Extension SDK (azure-devops-extension-sdk), please also check the usage of Azure DevOps Web API clients and contracts (azure-devops-extension-api), as well as Azure DevOps UI (azure-devops-ui) if needed ;

    Here are some more Azure DevOps Extension Samples for your reference.

    Login or Signup to reply.
  2. You’ll need to use the REST API to query for work items, such as Product Backlog Items, and then update them.

    npm install azure-devops-extension-sdk
    

    React component initialization:

    import * as SDK from "azure-devops-extension-sdk";
    import React, { useEffect } from "react";
    
    useEffect(() => {
        SDK.init();
    }, []);
    

    To authenticate and get an access token to make authenticated requests to the Azure DevOps REST API, use the SDK’s getAccessToken method:

    import { getAccessToken } from "azure-devops-extension-sdk";
    
    async function getAuthToken() {
        try {
            const token = await SDK.getAccessToken();
            return token;
        } catch (error) {
            console.error("Failed to get access token", error);
        }
    }
    

    Once you have the token, you can query work items using a WIQL query. Create a function to send a POST request to the Azure DevOps REST API endpoint for WIQL queries, including the token in the headers for authentication:

    async function queryWorkItems(token, query) {
        const organization = "your-organization"; // your Azure DevOps organization
        const project = "your-project"; // your Azure DevOps project
    
        const response = await fetch(`https://dev.azure.com/${organization}/${project}/_apis/wit/wiql?api-version=7.2`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({ query })
        });
    
        if (!response.ok) {
            throw new Error(`Error querying work items: ${response.statusText}`);
        }
    
        const result = await response.json();
        return result.workItems;
    }
    

    To update a work item, send a PATCH request to the appropriate Azure DevOps REST API endpoint, again including the token in the headers. This request will contain the updated fields in the request body formatted as JSON-patch:

    async function updateWorkItem(token, workItemId, fields) {
        const organization = "your-organization";
        const project = "your-project";
    
        const response = await fetch(`https://dev.azure.com/${organization}/${project}/_apis/wit/workitems/${workItemId}?api-version=7.2`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json-patch+json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify(fields)
        });
    
        if (!response.ok) {
            throw new Error(`Error updating work item: ${response.statusText}`);
        }
    
        const result = await response.json();
        return result;
    }
    

    Combine these steps by first querying for a work item by title, then using the ID of the found work item to send the update request. Create a function that queries for a work item with a specific title, and if found, updates its description:

    async function findAndUpdateWorkItemByTitle(title, newDescription) {
        try {
            const token = await getAuthToken();
    
            const query = `SELECT [System.Id] FROM workitems WHERE [System.Title] = '${title}'`;
            const workItems = await queryWorkItems(token, query);
    
            if (workItems.length === 0) {
                console.log("No work item found with the given title.");
                return;
            }
    
            const workItemId = workItems[0].id;
            const updateFields = [
                {
                    op: "add",
                    path: "/fields/System.Description",
                    value: newDescription
                }
            ];
    
            const updatedWorkItem = await updateWorkItem(token, workItemId, updateFields);
            console.log("Work item updated:", updatedWorkItem);
        } catch (error) {
            console.error("Error:", error);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search