Check for completed pipeline in Azure DevOps from WorkItem - c#

For a project I'm working on I have to get a Pull Request and Repository from an Azure DevOps WorkItem ID.
I'm using the Microsoft.TeamFoundationServer.Client NuGet-Package for this.
Now i also want to be able to check if a build pipeline ran successfully before moving on to further steps.
After trying to figure it out myself and not finding a single article on how to do that, I'm just gonna ask the question myself.
So, I already have:
the WorkItem object
the GitRepository object
the PullRequest object
And I want:
some form of pipeline object of that specific Pull Request/Commit
I hope there even is a way to get that.
Any help or references are apprechiated. Thanks!

I'm working on I have to get a Pull Request and Repository from an
Azure DevOps WorkItem ID.
For pull request that related to work item, I can write a C# code for you. But for the repository, I think there doesn't have a relationship between repository itself and work item in DevOps concept(link commit and work item is possible.).
Now i also want to be able to check if a build pipeline ran
successfully before moving on to further steps.
Do you mean you want the pipeline run status related to pull request? I checked the sdk definition, there doesn't have such definition, also no in the REST API. A possible solution is following the f12 to capture the API to get the build pipeline run id and it status.
Just a demo:
using System;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
namespace GetPipelineResults
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string url_string = "https://dev.azure.com/xxx/";
string personalAccessToken = "xxx";
Uri orgUrl = new Uri(url_string);
string project = "xxx";
int workitemId = 122;
var workitem = GetPullRequestAndRepositoryFromWorkItemId(orgUrl,personalAccessToken,workitemId);
var pullRequestUrl = workitem.Result.Relations[0].Url.ToString();
var pullRequestUrl2 = pullRequestUrl.Substring(pullRequestUrl.LastIndexOf('/') + 1);
string[] pullRequestUrl2Array = pullRequestUrl2.Split("%2F");
string pullRequestIdString = pullRequestUrl2Array[pullRequestUrl2Array.Length - 1];
Console.WriteLine(pullRequestIdString);
}
//Get Pull request from work item id
public static async Task<WorkItem> GetPullRequestAndRepositoryFromWorkItemId(Uri orgUrl, string personalAccessToken, int workItemId)
{
VssConnection connection = new VssConnection(orgUrl, new VssBasicCredential(string.Empty, personalAccessToken));
WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
WorkItemExpand workItemExpand = WorkItemExpand.All;
var workItem = workItemTrackingHttpClient.GetWorkItemAsync(workItemId, expand: workItemExpand).Result;
return workItem;
}
}
}

Related

Cast a CSOM (C#) request from Excel to perform an insert into SharePoint Online

Good afternoon,
I have got a "program" in VBA that has to write in a SharePoint Online list.
Problem:
I used to insert data from an excel file (via VBA) to a SharePoint 2013 list by connecting directivity to the database underlying (via ADODB connection).
With SharePoint Online this is no more possible, indeed I had to come up with a different solution by using CSOM (C#) library.
After struggling for a week to perform a well-done insert that satisfy all my needs…now I am stuck.
Goal:
I need a way in which VBA code can cast my insert (C#) by using the parameters that I communicate via VBA => Full Process/idea explained
I found some references c# - How to call .NET methods from Excel VBA? but for me it is difficult to implement it to my code.
This is my current code:
using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
using (ClientContext clientContext = new ClientContext("Sharepoint list URL"))
{
string Uname = "Username";
string password = "Password";
SecureString Securepasseord = GetSecureString(password);
clientContext.Credentials = new SharePointOnlineCredentials(Uname, Securepasseord); clientContext.ExecuteQuery();
clientContext.ExecuteQuery();
List oList = clientContext.Web.Lists.GetByTitle("Target List Name");
//clientContext.LoadQuery();
clientContext.ExecuteQuery();
ListItemCreationInformation listCreationInformation = new ListItemCreationInformation();
ListItem oListItem = oList.AddItem(listCreationInformation);
oListItem["Client"] = "John";
oListItem["City"] = "New York";
oListItem["Company"] = "ZXY";
oListItem.Update();
clientContext.ExecuteQuery();
}
}
private static SecureString GetSecureString(String Password)
{
SecureString oSecurePassword = new SecureString(); foreach (Char c in Password.ToCharArray()) { oSecurePassword.AppendChar(c); }
return oSecurePassword;
}
}
}
I thought about creating a JSON object to link the two, but if it will manage more than a request at the same time it would be a mess. I would like to keep a direct connection between these systems.
Thank you in advance for your answers.
Regards,
Daniele
Edit: for this project, I cannot use OneDrive/Excel Online solutions due to internal policies. I need to bring data to SharePoint in this way and then I can start working with Power Automate to manage all the notifications/approvals flows.
In the end, I solved the problem by using the Main(string [] args). I will pass data via the command line. Easy, direct, fast and reliable.
For example:
Client = args[0];
City = args[1];
Company= args[2];
....................
oListItem["Client"] = Client;
oListItem["City"] = City;
oListItem["Company"] = Company;

Azure service bus subscription metrics

I am trying to find the best way to see the last date a subscription in a topic was accessed via c# (SDK or otherwise) i.e. to purge the queue if not accessed in over x hours. I know there is that functionality built into the service bus explorer but have not been able to find any SDK functionality. If anyone could point me in the right direction it would be appreciated.
Please see the code below. It uses Azure.Messaging.ServiceBus SDK. The properties you're interested in is available in SubscriptionRuntimeProperties class.
using System;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus.Administration;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
string connectionString =
"connection-string";
string topicName = "topic-name";
string subscriptionName = "subscription-name";
ServiceBusAdministrationClient administrationClient = new ServiceBusAdministrationClient(connectionString);
var result = await administrationClient.GetSubscriptionRuntimePropertiesAsync(topicName, subscriptionName);
Console.WriteLine(result.Value.AccessedAt.ToString("yyyy-MM-ddTHH:mm:ss"));
}
}
}

Google Vision API not working Grpc.Core.RpcException

I'm trying to get Google Vision API to work with my project but having trouble. I keep getting the following error:
Grpc.Core.RpcException: 'Status(StatusCode=PermissionDenied, Detail="This API method requires billing to be enabled
I've created a service account, billing is enabled and I have the .json file. I've got the Environment variable for my account for GOOGLE_APPLICATION_CREDENTIALS pointing to the .json file.
I've yet to find a solution to my problem using Google documentation or checking StackOverFlow.
using Google.Cloud.Vision.V1;
using System;
using System.Collections.Generic;
namespace Vision
{
internal static class GoogleVision
{
public static EntityAnnotation[] GetAnnotations(EventManager em, string filePath, string EventNr)
{
{
ImageAnnotatorClient Client = ImageAnnotatorClient.Create();
Image Image = Google.Cloud.Vision.V1.Image.FromFile(filePath);
IReadOnlyList<EntityAnnotation> Response = Client.DetectLabels(Image);
EntityAnnotation[] annotations = new EntityAnnotation[Response.Count];
for (int i = 0; i < annotations.Length; i++)
{
annotations[i] = Response[i];
}
return annotations;
}
}
}
}
Not sure why but by setting the environment variable in the code rather than manually with windows, it fixed the problem.
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "thejsonfile");

Retrieve TFS Test Steps always returns count of 0

I am trying to retrieve test steps (aka "actions") that have been added to a test case in TFS (2017.2) using the API (Microsoft.TeamFoundationServer.ExtendedClient v15.112.1). My current implementation always returns 0 test steps, although the actual test case has steps. I tried this as well in a clean new Team Project without any Work Item customization and even there it returns 0 steps. My implementation uses the older API (based on SOAP webservices), because it seems the newer http based API does not yet implement test steps. This is the code I have used:
private void GetTestStepsForTestCase(int testCaseId, int testSuiteId,
string teamProjectName, Uri tfsUrl)
{
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(tfsUrl);
ITestManagementService itms = tpc.GetService<ITestManagementService>();
ITestManagementTeamProject ittp = itms.GetTeamProject(teamProjectName);
ITestSuiteBase suite = ittp.TestSuites.Find(testSuiteId);
ITestCaseCollection testCaseCollection = suite.AllTestCases;
ITestCase itestCase = testCaseCollection.FirstOrDefault(t => t.Id == testCaseId);
foreach (Microsoft.TeamFoundation.TestManagement.Client.ITestAction itestAction in itestCase.Actions)
{
// Do something
}
}
Anyone?
You can use below sample to retrieve the test case steps from a specific test suite, it works on my side:
Install the nuget package : Microsoft.TeamFoundationServer.ExtendedClient - 15.112.1
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.TestManagement.Client;
using Microsoft.VisualStudio.Services.Client;
using System;
namespace RetrieveTestSteps
{
class Program
{
static void Main(string[] args)
{
var u = new Uri("http://server:8080/tfs/DefaultCollection");
var c = new VssClientCredentials();
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(u, c);
tpc.EnsureAuthenticated();
ITestManagementService itms = tpc.GetService<ITestManagementService>();
ITestManagementTeamProject ittp = itms.GetTeamProject("LCScrum");
ITestSuiteBase suite = ittp.TestSuites.Find(352);
ITestCaseCollection testCaseCollection = suite.AllTestCases;
foreach (var tc in testCaseCollection)
{
ITestCase testcase = ittp.TestCases.Find(tc.Id);
foreach (ITestAction action in testcase.Actions)
{
Console.WriteLine(String.Format("{0} - {1}", testcase.Id, action));
}
}
Console.Read();
}
}
}
OK, I finally figured out this one myself. The answer and comments of Andy helped me validate that my code is correct. I just discovered that my code worked fine when NOT debugging! When debugging, at some point I noticed this:
So probably because of lazy loading somewhere, it is not possible to verify the count of the attachments debug-time (see post here: Lazy<T>: "The function evaluation requires all threads to run").

test build agents of a build controller using tfs api

I want to automate testing of newly created build agents in TFS.
Now, I have written code to queue builds of particular build definition on TFS.
Problem I am facing is to queue build definition on agents of given controller.
Previously there was one method which I've commented in my code
for doing this, i.e. IbuildRequest.buildagent, but now it has been deprecated in newer tfs api.
Edit:
I have already tested IbuildRequest.BuildController property which tends to randomly pick agent, which is currently free.
What I want to know is can I force build definition to use one build Agent using tfs api.
using System;
using System.Linq;
using System.Security.Principal;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace BuildAgentsTestApp
{
class Program
{
static void Main(string[] args)
{
Uri collectionURI = new Uri("https://tfs-uri");
var tfsCreds = new TfsClientCredentials(new WindowsCredential(), true);
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(collectionURI,tfsCreds);
WindowsIdentity user = WindowsIdentity.GetCurrent();
tfs.EnsureAuthenticated();
if (tfs.HasAuthenticated)
{
WorkItemStore workItemStore = tfs.GetService<WorkItemStore>();
Project teamProject = workItemStore.Projects["myProjectName"];
IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
IBuildDefinition buildDef = buildServer.GetBuildDefinition(teamProject.Name, "myBuildDefinitionName");
var controller = GetRequestedController(buildServer, "myControllerName");
var AgentsList = GetAgentCollection(controller);
//Queue each build definition
IBuildRequest buildRequest = buildDef.CreateBuildRequest();
buildRequest.GetOption = GetOption.Custom;
//buildRequest.BuildAgent = AgentsList.First();
buildServer.QueueBuild(buildRequest);
}
Console.WriteLine("Build Queued!");
Console.ReadKey();
}
static IBuildController GetRequestedController(IBuildServer reqBuildServer, string reqControllerName)
{
var requiredController = reqBuildServer.QueryBuildControllers()
.Where(ctrl =>
ctrl.Name == reqControllerName
).FirstOrDefault();
return requiredController;
}
static List<IBuildAgent> GetAgentCollection(IBuildController controller)
{
var ListOfAgents = from agent in controller.Agents
select agent;
return ListOfAgents.ToList();
}
}
}

Categories

Resources