Create Release to Run Tests on Azure DevOps Release Pipeline via C#

Introduction

In the realm of modern software development, automation is key to maintaining efficiency and consistency. Azure DevOps offers robust tools for continuous integration and continuous deployment (CI/CD), allowing you to streamline your release management processes. In this blog, we’ll walk you through the steps to create a release on Azure DevOps using C# code — and link it to a Test Run for full traceability. Whether you’re a seasoned developer or just starting with Azure DevOps, this guide will help you harness the power of automation.

What You'll Need

  1. Azure DevOps Account: If you don’t have one, sign up at Azure DevOps Services.
  2. Personal Access Token (PAT): You’ll need this for authentication. Click the Settings icon next to your profile icon, then click Personal access tokens.
    Azure DevOps settings menu showing the Personal access tokens option

    Click New Token and enter the required details in the screen below:

    Create a new personal access token dialog in Azure DevOps
  3. Visual Studio or any C# IDE: For writing and running your C# code.
  4. NuGet Packages: We’ll use the following NuGet packages for interacting with Azure DevOps:
    • Microsoft.TeamFoundationServer.Client
    • Microsoft.VisualStudio.Services.Release.Client
⚠️ Security Tip: Treat your PAT like a password. Never commit it to source control — load it from an environment variable or a secret store, and grant it only the scopes you need (Release: Read & Write, Test Management: Read & Write).

Setting Up Your Environment

  1. Create a Console Application:
    • Open Visual Studio and create a new C# Console Application project.
    • Name your project appropriately (e.g., AzureDevOpsReleaseCreator).
  2. Add NuGet Packages:
    • Right-click your project in Solution Explorer and select Manage NuGet Packages.
    • Search for Microsoft.TeamFoundationServer.Client and Microsoft.VisualStudio.Services.Release.Client and install them. These packages contain the libraries needed to interact with Azure DevOps Services.

Writing the C# Code

1. Initialize the Azure DevOps Connection

First, establish a connection to Azure DevOps using your PAT and organisation URL. Replace {YourOrganisation} with your Azure DevOps organisation name and {YourPAT} with your Personal Access Token.

using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;

// Your organisation URL and Personal Access Token
var organisationUrl = new Uri("https://dev.azure.com/{YourOrganisation}");
var pat = Environment.GetEnvironmentVariable("AZDO_PAT"); // {YourPAT}

var credentials = new VssBasicCredential(string.Empty, pat);
var connection = new VssConnection(organisationUrl, credentials);

2. Create a Test Run

In the CreateTestRunAsync method, pass a TestRunName (any descriptive string), the TestPlanId, and an integer array of pointIds (Point IDs can be obtained using TestPlanHttpClient).

using Microsoft.TeamFoundation.TestManagement.WebApi;

async Task<TestRun> CreateTestRunAsync(
    string projectName, string testRunName,
    int testPlanId, int[] pointIds)
{
    var testClient = connection.GetClient<TestManagementHttpClient>();

    var runModel = new RunCreateModel(
        name: testRunName,
        plan: new ShallowReference(testPlanId.ToString()),
        pointIds: pointIds);

    return await testClient.CreateTestRunAsync(runModel, projectName);
}

3. Create the Release

Once the Test Run is created, create a release by passing the BuildId (from the build created under the Pipelines section) and the Release DefinitionId (the unique identifier assigned to each release definition under the Releases section in Azure DevOps).

using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi;
using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Clients;

async Task<Release> CreateReleaseAsync(
    string projectName, int releaseDefinitionId, string buildId)
{
    var releaseClient = connection.GetClient<ReleaseHttpClient>();

    var artifact = new ArtifactMetadata
    {
        Alias = "{YourArtifactAlias}", // as shown in the release definition
        InstanceReference = new BuildVersion { Id = buildId }
    };

    var releaseMetadata = new ReleaseStartMetadata
    {
        DefinitionId = releaseDefinitionId,
        Description = "Release created via C# automation",
        Artifacts = new List<ArtifactMetadata> { artifact }
    };

    return await releaseClient.CreateReleaseAsync(releaseMetadata, projectName);
}

4. Update the Test Run

Once the Test Run and Release are created, update the Test Run by linking it to the release created in the previous step.

async Task UpdateTestRunAsync(
    string projectName, TestRun testRun, Release release)
{
    var testClient = connection.GetClient<TestManagementHttpClient>();

    var updateModel = new RunUpdateModel(
        comment: $"Linked to release {release.Name}",
        releaseUri: release.Url);

    await testClient.UpdateTestRunAsync(updateModel, projectName, testRun.Id);
}

5. Update the Release

Next, update the release by passing the release object created in step 3 and the TestRunId (obtained from the Test Run created in step 2).

async Task<Release> UpdateReleaseAsync(
    string projectName, Release release, int testRunId)
{
    var releaseClient = connection.GetClient<ReleaseHttpClient>();

    release.Description = $"Validated by Test Run {testRunId}";

    return await releaseClient.UpdateReleaseAsync(release, projectName, release.Id);
}

6. Update the Release Environment

The last step is to update the release environment to trigger the deployment. Once the release environment is updated, you will be able to see the release under the Releases section for the release definition whose Release Definition Id you passed.

async Task UpdateReleaseEnvironmentAsync(
    string projectName, Release release)
{
    var releaseClient = connection.GetClient<ReleaseHttpClient>();

    var environment = release.Environments.First();

    var updateMetadata = new ReleaseEnvironmentUpdateMetadata
    {
        Status = EnvironmentStatus.InProgress,
        Comment = "Deployment triggered via C# automation"
    };

    await releaseClient.UpdateReleaseEnvironmentAsync(
        updateMetadata, projectName, release.Id, environment.Id);
}

7. Run Your Code

  • Build and run your application.
  • You should now see the newly created release under the Releases section and the newly created Test Run under the Test Runs section.
✅ Success Check: In Azure DevOps, open Pipelines → Releases to verify your new release, and Test Plans → Runs to see the linked Test Run — giving you full traceability from build to release to test results.

Testing and Troubleshooting

  1. Check Azure DevOps: Navigate to the Releases section of your project to verify the release has been created.
  2. Debugging: If you encounter issues, make sure your PAT has the appropriate permissions (Release and Test Management scopes) and that all IDs and names are correct. A 401 Unauthorized usually means an expired or under-scoped PAT; a 404 usually means a wrong project name or definition ID.

Conclusion

Automating the creation of releases with C# can save you time and reduce the risk of manual errors. By leveraging the Azure DevOps APIs through the Microsoft.TeamFoundationServer.Client and Microsoft.VisualStudio.Services.Release.Client packages, you can seamlessly integrate release creation — with linked test runs — into your CI/CD workflows.

Feel free to expand upon this basic example by integrating it with other automation scripts or extending the functionality to handle more complex release scenarios.

Happy coding, and may your releases be smooth and bug-free!

Comments

Post a Comment

Popular posts from this blog

Send Emails from Azure DevOps Pipelines: Build a Custom SendGrid Extension