Azure DevOps continues to amaze me as one of the most capable and configurable Azure services. Whether it’s for code repositories, pipelines, project management, or some sweet Wiki action, Azure DevOps can provide a complete DevOps tooling solution. And what it can’t do out-of-the-box, integration with your favorite external system can be much easier than you think.
Let’s take a recent (and very common) scenario I had with a client:
“We are using Azure DevOps for our Agile process. When we update child work item to 'In Progress', why doesn’t the parent status update, as well?”
It’s a valid question. Logically, you would think that any Project Management solution would do this, because it’s such a natural thing to occur. When it comes to software, though, things are never so simple. Azure DevOps and similar tools often don’t implement this because the variables could be all over the place for each organization. What work items should be updated? What state should they be updated to? What states should NOT be updated? Where are my car keys?
As you can see, the question leads to a lot of unknowns. Covering every single scenario would be a huge undertaking, and even then, something wouldn’t be covered. The solution? Service Hooks and Azure Functions. Don’t worry, it’s not as complex as it sounds. Let me show you…
To access Azure DevOps from another system. I need to generate a PAT. This token will be used to validate my integration with Azure DevOps and should be treated as very sensitive information. In my Azure DevOps User Settings, I create a new Personal Access Token. I set an appropriate expiration date and give Read, Write, & Manage permissions to Work Items.
Because that magic code is obfuscated once I leave the screen, I copy for use later in the process.
In my Azure Key Vault, I create a secret for the Azure DevOps PAT.
On the secret details, I copy the URL for the current secret version.
In the demo Azure Function project, there are four (4) settings that need to be configured.
When developing/testing locattion, I update the localsettings.json file with my values.
When running in Azure, I add my App Settings to the Azure Function app.
Here is my App Settings configuration after adding 3 of the settings.
Here is the App Settings configuration after adding the Key Vault reference.
To confirm the Azure Function is able to access the Azure Key Vault, I click on the app setting and confirm it displays a Resolved status.
With the Azure Function and Key Vault configured, I am ready to add my Azure DevOps Service Hook. Service Hooks enable the execution of code when an event occurs within Azure DevOps. Create a new service hook to call the Azure Function when a work item state is updated.
In my Azure DevOps project, I select Project Settings and then Service hooks.
I select Web hooks for the Service type.
I select the Work item updated trigger.
There are several types of triggers for Azure DevOps service hooks. Be sure to review the available options and select the appropriate option for your needs.
I select the State field.
In my example, I need to update the parent work item’s State when a child work item is updated. I select the State field to ensure the service hook is only executed when that field is updated.
Remember the Function URL? I get that value from the Azure Portal (Azure Function>Functions>Overview>Get Function Url) to use for the next step.
I enter the Azure Function Url in the Action>URL field.
With all the components deployed, I am ready to test the functionality.
To test the integration, I will update a work item within my Azure DevOps demo project and monitor the services.
I open the Azure Function Log (Azure Function>Functions>[Function Name]>Monitor>Logs). Live streaming messages will be displayed here when the function executes.
In Azure DevOps, I open the Service Hook and ensure it is enabled.
In Azure DevOps, I open my project and view a Backlog to view a hierarchy of work items. I select child work item to edit.
I update the State to any value other than the DevOpsDefaultState (New) in my configuration.
In the demo Azure Function project, I only update the parent work item if the status of the child work is different than the DevOpsDefaultState setting. This may differ for your DevOps project and Agile processes.
I refresh the Backlog and ensure the parent work items are properly updated to the DevOpsUpdateState in my configuration (In Progress).
This may take up to a minute to update as the Azure Function executes. The Azure Function will be executed recursively for the tree.
In the Azure Function Log, I confirm the function was executed.
Lastly, in the Azure DevOps Service Hook page, I confirm the service hook executed successfully.
There are 3 executions of the service hook, 1 for each level of the hierarchy. Because the Azure Function updates the Azure DevOps parent work item via the SDK, it causes the service hook to fire for that item, as well. This will recursively “climb” up the tree for all parent work items.
I click the History link to view details on each service hook execution. This can be especially helpful in determining what the service hook request contains and the response Azure DevOps receives from the Azure Function.
By leveraging Azure DevOps service hooks and Azure Functions, you can easily modify any aspect of your Azure DevOps project. Service Hooks offer a wide range of triggers, allowing you to customize the automation to fit your needs. By using Azure Key Vault, you ensure that your sensitive data is kept secure.
In searching for a solution to my client’s question, I didn’t find a lot of articles on this topic. I hope this article provides you a great starting point for your Azure DevOps. Be sure to check out the Helpful Links below for several reference sites. Good luck!