Retrieve VSTS/TFS Build task name list - tfs

I need to retrieve build task name list from VSTS/TFS build. Is there inbuilt method/library available to support this?
I have already noted (as below sample) that we can retrieve same in release.
import ReleaseClient = require("ReleaseManagement/Core/RestClient");
var rc= ReleaseClient.getClient();
release.environments.forEach(function (env) {
rc.getTasks(VSS.getWebContext().project.id, release.id, env.id).then(function(taskList){
...............
......Some code here
});
}

The documentation doesn't show a direct function call to retrieve the tasks. However, there is a contract for a BuildDefinition, which contains a build property, which is an array of BuildDefinitionStep, each of which has a task property that contains things like the name of the task and the inputs.
The getDefinition() function should give you back a build definition you can work with.
import RestClient = require("TFS/Build/RestClient");
// Get an instance of the client
var client = RestClient.getClient();
var myDefinition client.getDefinition(1234);

Related

Genexus Extensions SDK - Where can I find the avaliable Menu Context strings?

Im trying to use the Genexus Extensions SDK to place buttons on the IDE, in this case, i want to place it in the "context" menu, avaliable only in objects of type "Webpanel/Webcomponent" and "Transaction", Just like WorkWithPlus does here:
So far, digging up into the avaliable documentation, i've noticed that you need tu put the context type string into the xml tag and the GUID of the package that you're aiming to add the menu item, such as below in GeneXusPackage.package:
The Context ID above will add the item into the "Folder View" Context.
My questions:
Where can I find a list with all the possible ID Context strings?
What is that package attribute for, where can i get it's possible values?
I am using the SDK for Genexus 16 U11
I'm sorry to say that there is no extensive list of all the menus available. I'd never thought of it until now, and I see how it could be useful, so we'll definitely consider making it part of the SDK so that any package implementor may use it for reference.
In the meantime, in order to add a new command in the context menu you mentioned, you have to add it to the command group that is listed as part of that menu. That group is KBObjectGrp which is provided by the core shell package whose id is 98121D96-A7D8-468b-9310-B1F468F812AE.
First define your command in your .package file inside a Commands section:
<Commands>
<CommandDefinition id='MyCommand' context='selection'/>
</Commands>
Then add it to the KBObjectGrp mentioned earlier.
<Groups>
<Group refid='KBObjectGrp' package='98121D96-A7D8-468b-9310-B1F468F812AE'>
<Command refid='MyCommand' />
</Group>
</Groups>
Then in order to make your command available only to the objects you said before, you have to code a query handler for the command, that will rule when the command is enabled, disabled, or not visible at all. You can do that in the Initialize method of your package class.
public override void Initialize(IGxServiceProvider services)
{
base.Initialize(services);
CommandKey myCmdKey = new CommandKey(Id, "MyCommand");
AddCommand(myCmdKey, ExecMyCommand, QueryMyCommand);
}
private bool QueryMyCommand(CommandData data, ref CommandStatus status)
{
var selection = KBObjectSelectionHelper.TryGetKBObjectsFrom(data.Context).ToList();
status.Visible(selection.Count > 0 && selection.All(obj => obj.Type == ObjClass.Transaction || obj.Type == ObjClass.WebPanel));
return true;
}
private bool ExecMyCommand(CommandData data)
{
// Your command here
return true;
}
I'm using some helper classes here in order to get the objects from the selection, and then a class named ObjClass which exposes the guid of the most common object types. If you feel something isn't clear enough, don't hesitate to reach out.
Decompiling the Genexus dll and looking for the resource called package, you can infer what the names are.
It's cumbersome but it works

How can I push data written by a Serilog File Sink on the disk to another Serilog sink?

We are trying to load test our infrastructure of logstash/elastic. Since the actual logs are generated by a software that uses hardware, we are unable to simulate it at scale.
I am wondering if we can store the logs using file sink and later write a program that reads the log files and send data through the actual sink. Since, we are trying different setup, it would be great if we can swap different sinks for testing. Say http sink and elastic sink.
I thought of reading the json file one line at a time and then invoking Write method on the Logger. However I am not sure how to get the properties array from the json. Also, it would be great to hear if there are better alternatives in Serilog world for my needs.
Example parsing
var events= File.ReadAllLines(#"C:\20210520.json")
.Select(line => JsonConvert.DeserializeObject<dynamic>(line));
foreach (var o in objects)
{
DateTime timeStamp = o.Timestamp;
LogEventLevel level = o.Level;
string messageTemplate = o.MessageTemplate;
string exception = o.Exception;
var properties = (o.Properties as JObject);
List<object> parameters = new List<object>();
foreach (var property in properties)
{
if(messageTemplate.Contains(property.Key))
parameters.Add(property.Value.ToString());
}
logInstance.Write(level, messageTemplate, parameters.ToArray());
count++;
}
Example Json Event written to the file
{"Timestamp":"2021-05-20T13:15:49.5565372+10:00","Level":"Information","MessageTemplate":"Text dialog with {Title} and {Message} displayed, user selected {Selected}","Properties":{"Title":"Unload Device from Test","Message":"Please unload the tested device from test jig","Selected":"Methods.Option","SinkRepository":null,"SourceRepository":null,"TX":"TX2937-002 ","Host":"Host1","Session":"Host1-2021.05.20 13.12.44","Seq":87321,"ThreadId":3}}
UPDATE
Though this works for simple events,
it is not able to handle Context properties (there is a work around though using ForContext),
also it forces all the properties to be of type string and
not to mention that destucturing (#property) is not handled properly
If you can change the JSON format to Serilog.Formatting.Compact's CLEF format, then you can use Serilog.Formatting.Compact.Reader for this.
In the source app:
// dotnet add package Serilog.Formatting.Compact
Log.Logger = new LoggerConfiguration()
.WriteTo.File(new CompactJsonFormatter(), "./logs/myapp.clef")
.CreateLogger();
In the load tester:
// dotnet add package Serilog.Formatting.Compact.Reader
using (var target = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.Console()
.CreateLogger())
{
using (var file = File.OpenText("./logs/myapp.clef"))
{
var reader = new LogEventReader(file);
while (reader.TryRead(out var evt))
target.Write(evt);
}
}
Be aware though that load testing results won't be accurate for many sinks if you use repeated timestamps. You should consider re-mapping the events you read in to use current timestamps.
E.g. once you've loaded up evt:
var current = new LogEvent(DateTimeOffset.Now,
evt.Level,
evt.Exception,
evt.MessageTemplate,
evt.Properties);
target.Write(current);

How to deal with json data read from a database with RPC package

I try to implement an API using the RPC dart package.
In all the example I found, response are build manually (ie new Response()..message = "hello").
In my case, i read JSON data from mongodb and want to return them with minimal transformation (basically picking only external properties).
The fromRequest of the method schema can be used to do this :
class QueryResult {
//my props
}
#ApiMethod(path: "myMongoQuery")
Future<List<QueryResult>> myMongoQuery() async {
var schema = _server.apiMap["/query/v1"].schemaMap["QueryResult"];
var results = await coll.find();
return results.map(schema.fromRequest).toList();
}
The problem in my code is the first line (_server.apiMap["/query/v1"].schemaMap["QueryResult"]) it's a pure hack to retrieve the schema of my method.
I tried to use mirror to retrieve the schema in an elegant/generic way but did not succeed.
Anyone can help me on this ?
Cheers,
Nicolas

TFS Workflow - Show Test Suites in Custom Editor

[Edit]
You can get the current build-def via the IServiceProvider. See this answer.
[/Edit]
I'm trying to add a custom editor for one of our TFS Xaml build workflows.
I started by following this excelent tutorial by Ewald Hofman.
Everything worked as expected, when I click on the [...] button for the workflow parameter the credential dialog is displayed.
What I want to do:
I want to display a selectable list/tree of test suites that are available in the TFS team project. Just like in the Default Labs Workflow:
Obviously, for this to work, I have to be able to communicate the the TFS over its .Net-API (Is it possible to do via SOAP/REST?).
But whenI started to alter the example to fit to my scenario, I naivly tried using the IServiceProvider to get ahold of an IBuildService instance.
public override object EditValue(ITypeDescriptorContext context, ServiceProvider provider, object value)
{
if (provider != null)
{
IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
IBuildServer bs = (IBuildServer)provider.GetService(typeof(IBuildServer));
...
This approach did not work, bs is null after this statement.
Then I tried to connect to the TestManagement like this:
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection/ProjectName"));
var TcmService = pr.GetService<ITestManagementService>();
var t = TcmService.GetTeamProject("ProjectName");
But this failed with a HTTP 404 error that is displayed when I click the edit [...] buttton of the workflow parameter. The url is correct, if i open the page in a browser, the Team Webaccess page is displayed.
TL;DR:
I would like to be able to display a list of test suites of the current tfs in a custom worfklow parameter editor, but I am failing to connect to the TFS.
Other approach:
This site (and some others) recommend using builtin editors. Is it possible to use the builtin editor window of the labs workflow paramaters (the one in the first screenshot)?
Thanks in advance.
Appearantly I was just stupid.
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection/ProjectName"));
The project name must not be in this URL. With the line below it works just fine.
var pr = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://tfs:8080/tfs/DefaultCollection"));
See my followup question

How to retrieve a list of Changesets (or work items) that were checked-in between builds?

I need a list of changesets (or Work Items) that were made betweend builds (I can label builds if its necessary).
I need that list for our test team (and to publish 'changelist').
Is MSBuild task able to retrieve that list and save as file (then I can process that list further.
Or maybe I need to connect to TFS from C# code and retrieve that list myself (I'm familiar with retrieving WorkItems in C#).
I know this thread is a couple of years old, but I found it when trying to accomplish the same thing.
I've been working on this for a couple of days now, and came up with a solution that accomplishes this specific task. (TFS 2010)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Build.Client;
namespace BranchMergeHistoryTest
{
class Program
{
private static Uri tfsUri = new Uri("http://sctf:8080/tfs");
private static TfsTeamProjectCollection tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(tfsUri);
static void Main(string[] args)
{
IBuildServer buildServer = tfs.GetService<IBuildServer>();
IBuildDefinition buildDef = buildServer.GetBuildDefinition("Project", "Specific Build");
IOrderedEnumerable<IBuildDetail> builds = buildServer.QueryBuilds(buildDef).OrderByDescending(build => build.LastChangedOn);
/* I had to use some logic to find the last two builds that had actual changesets attached - we have some builds that don't have attached changesets. You may want to do the same. */
IBuildDetail newestBuild = builds.ElementAt(0);
IBuildDetail priorBuild = builds.ElementAt(1);
string newestBuildChangesetId = newestBuild.Information.GetNodesByType("AssociatedChangeset")[0].Fields["ChangesetId"];
string priorBuildChangesetId = priorBuild.Information.GetNodesByType("AssociatedChangeset")[0].Fields["ChangesetId"];
VersionControlServer vcs = tfs.GetService<VersionControlServer>();
const string sourceBranch = #"$SourceBranch-ProbablyHEAD";
const string targetBranch = #"$TargetBranch-ProbablyRelease";
VersionSpec versionFrom = VersionSpec.ParseSingleSpec(newestBuildChangesetId, null);
VersionSpec versionTo = VersionSpec.ParseSingleSpec(priorBuildChangesetId, null);
ChangesetMergeDetails results = vcs.QueryMergesWithDetails(sourceBranch, VersionSpec.Latest, 0, targetBranch,VersionSpec.Latest, 0, versionFrom, versionTo, RecursionType.Full);
foreach(Changeset change in results.Changesets)
{
Changeset details = vcs.GetChangeset(change.ChangesetId);
// extract info about the changeset
}
}
}
}
Hope this helps the next person trying to accomplish the task!
I know this is old post but I have been digging around for how to accomplish this for many hours and I thought someone else might benefit from what I have put together. I am working with TFS 2013 and this was compiled together from several different sources. I know I don't remember them all at this point but the main ones where:
Get Associated Changesets from Build
Queue a Team Build from another and pass parameters
What I was missing from most articles I found on this subject was how to take the build detail and load the associated changesets or work items. The InformationNodeConverters class was the missing key for this and allows you to get other items as well. Once I had this I was able to come up with the following code that is pretty simple.
Note that if you are running this from a post build powershell script you can use the TF_BUILD_BUILDURI variable. I have also included the code that I came up with to take the summary data retrieved and load the actual item.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace Sample
{
class BuildSample
{
public void LoadBuildAssociatedDetails(Uri tpcUri, Uri buildUri)
{
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tpcUri);
IBuildServer buildServer = collection.GetService<IBuildServer>();
IBuildDetail buildDetail = buildServer.GetAllBuildDetails(buildUri);
List<IChangesetSummary> changeSets = InformationNodeConverters.GetAssociatedChangesets(buildDetail);
VersionControlServer vcs = collection.GetService<VersionControlServer>();
IEnumerable<Changeset> actualChangeSets = changeSets.Select(x => vcs.GetChangeset(x.ChangesetId));
List<IWorkItemSummary> workItems = InformationNodeConverters.GetAssociatedWorkItems(buildDetail);
WorkItemStore wis = collection.GetService<WorkItemStore>();
IEnumerable<WorkItem> actualWorkItems = workItems.Select(x => wis.GetWorkItem(x.WorkItemId));
}
}
}
TFS will automatically produce a list of all change sets and associated work items checked-in between two successful builds. You will find the lists at the end of the build report.
You could set up a build that is used to communicate with the testers. When that build is build successfully the testers could just look at the build report to see what work items and change sets has been committed since the last build.
If you set up an event listener for the build quality property of a build you could send an email alert to the testers when that builds quality filed changes to a specific version.
We have build labels for each build, they are the same as build number, which is the same as the product version number that our QA and Support operate on.
So, this works for us:
tf.exe history <BRANCH> /version:L<BUILD_NUMBER_FROM>~L<BUILD_NUMBER_TO> /recursive /collection:http://<our TFS server>
results look like this:
Changeset User Date Comment
--------- ----------------- ---------- ------------------------------------- ----------------
3722 Sergei Vorobiev 2013-11-16 Merge changeset 3721 from Main
3720 <redacted>
3719 <redacted>
This blog post may be what you are looking for. You basically go through all the links finding ones with a Uri containing 'changeset'. There doesn't seem to be a specific property for this.
Link
(copied from blog in case of rot)
using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.VersionControl.Client;
class ChangesetsFromWorkItems
{
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.Error.Write("Usage: ChangesetsFromWorkItems <server> <workitemid> [workitemid...]");
Environment.Exit(1);
}
TeamFoundationServer server = TeamFoundationServerFactory.GetServer(args[0]);
WorkItemStore wiStore = (WorkItemStore)server.GetService(typeof(WorkItemStore));
VersionControlServer vcs = (VersionControlServer) server.GetService(typeof(VersionControlServer));
int workItemId;
for (int i = 1; i < args.Length; i++)
{
if (!int.TryParse(args[i], out workItemId))
{
Console.Error.WriteLine("ignoring unparseable argument {0}", args[i]);
continue;
}
WorkItem workItem = wiStore.GetWorkItem(workItemId);
List<Changeset> associatedChangesets = new List<Changeset>();
foreach (Link link in workItem.Links)
{
ExternalLink extLink = link as ExternalLink;
if (extLink != null)
{
ArtifactId artifact = LinkingUtilities.DecodeUri(extLink.LinkedArtifactUri);
if (String.Equals(artifact.ArtifactType, "Changeset", StringComparison.Ordinal))
{
// Convert the artifact URI to Changeset object.
associatedChangesets.Add(vcs.ArtifactProvider.GetChangeset(new Uri(extLink.LinkedArtifactUri);
}
}
}
// Do something with the changesets. Changes property is an array, each Change
// has an Item object, each Item object has a path, download method, etc.
}
}
}
We do something similar in our TFS Build process. To do this we created a MSBuild custom task in C# that makes the call to TFS for the items. It is pretty straight forward to create the custom tasks.
Here is an article to get you started with writing MSBuild tasks. http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
I assume you already know how to do the calls to TFS based on your question.
I posted a blog article on how to do this here: Getting a List of Changes After a Specified Build/Label from TFS 2013. It provides a quick and concise function for retrieving the list of files that have been changed since a given Build/Label.
Hope that helps!

Resources