Programmatically add new iteration in TFS - c#

I can manually add a new iteration to a team project in TFS by right clicking on the project and going to Team Project Settings > Areas and Iterations > Iterations tab.
Is there an example out there of how to do this programmatically using their API?
Thanks!

After some experimentation based on taylonr's link, here's what I came up with as a minimal solution for adding an iteration, in case any one else runs into this:
public void AddIteration(string projectName, string iterationName)
{
using (var tfsCollection = new TfsTeamProjectCollection(new Uri(tfsServerUrl), getTfsCredentials()))
{
tfsCollection.Authenticate();
var css = tfsCollection.GetService<ICommonStructureService>();
string rootNodePath = string.Format("\\{0}\\Iteration", projectName);
var pathRoot = css.GetNodeFromPath(rootNodePath);
css.CreateNode(iterationName, pathRoot.Uri);
}
}

Does this tutorial solve your problem?
http://blogs.microsoft.co.il/blogs/shair/archive/2009/01/30/tfs-api-part-10-add-area-iteration-programmatically.aspx
Google-Fu "tfs api add iteration"
From glancing at his code, (and using TFS) it looks like iterations are getting treated as hierarchies. That's why you see things like "Release1\Sprint2" etc... you can have them nested deep... deep down they're probably just a path and that's why he's using the add path etc

Related

Anyone know how to call a feature file fromthe middle of the code - Specflow & c#

Good morning / Afternoon
I have a main class that runs a lot of specific items that include calls to DB, etc.
In the middle of the code I want the code to run a list of specific feature files (specflow) but with all the previous parameters included
I have tried everything but I cannot seem to get it to work.
Anyone got some suggestions?
Thanks
Part of code attached
foreach (string element in Features)
{
DriversPage drivers = new DriversPage(mainRun, steps);
mainRun.TestRunNumber = dataBases.getRunNumberFromDB();
steps.TestRunNumber = mainRun.TestRunNumber; steps.InitializeStep();
drivers.InitializeDriver(element); steps.TerminateStep();
steps.UpdateCollections();
//CALL FEATURE FILE HERE!!!!
steps.UpdateCollections();
}

Libgit2sharp Get remote branches

Maybe asked before, but I cannot find the clear answer. When I need to list the branches of a repo with gitlib2sharp, do I really first need to clone to a local repo? What is the sense in that? I just want to clone a specific branch, like you do with git clone https://bla/repo.git -b branch1
Now I first need to do a local checkout, then get the branches and from there do a second round.
Am I missing something here (hope I do).
TIA for your answer!
Grtz,
Ronald
Update (to long for comment):
OK, so here's the use case. A company delivers ssrs reports, which we need to deploy through TAP. So my thoughts were to do this via Git. For each change let them create a branche, upload/alter/etc in this branche. And iterate changes in this branch till all is fine. In the iterations they should be able to (re)deploy themselves on at least T. At the final stage we merge the brnanch to master and (re)deploy master in P. In Github you can completely 'click' this flow, but of course I want to automate this and have preferably someelse push the buttons, so they don't need me for this. So what's the best programmatic choice here? When they make a branch and start deploying in T, should I create (clone) the repo, point my local repo to the specific branch, get the files (.sql and .rdl files) and execute/upload these? I was not aware that when you clone a repo, you clone all the branches with it. Thanks so far already!
If you want to do something like git clone https://bla/repo.git -b branch1 with libgtk2sharp try this one:
var exampleRepositoryUrl = "https://github.com/npgsql/npgsql.git";
var exampleDestinationFolder = "branch-hotfix-3.0.8";
var exampleBranchName = "hotfix/3.0.8";
var repositoryClonedPath = Repository.Clone(exampleRepositoryUrl,
exampleDestinationFolder,
new CloneOptions()
{
BranchName = exampleBranchName
});
using (var clonedRepo = new Repository(repositoryClonedPath))
{
// ...
}
To list names of remote branches without cloning a repo you can use something like this:
var branches = Repository.ListRemoteReferences(exampleRepositoryUrl)
.Where(elem => elem.IsLocalBranch)
.Select(elem => elem.CanonicalName
.Replace("refs/heads/", ""));
PiKos answer worked for me, but I had to set a credentials handler, e.g.:
var branches = Repository.ListRemoteReferences(exampleRepositoryUrl, MyCredentialsHandler)
.Where(elem => elem.IsLocalBranch)
.Select(elem => elem.CanonicalName
.Replace("refs/heads/", ""));
For more details on how to set a custom credentials handler, see this answer:
https://stackoverflow.com/a/55371988/5507590

How to get all changes to a file in Git, with Lib2GitSharp

I want to be able to Get a list of all changes done to a file. I've seen this post
How to get file's contents on Git using LibGit2Sharp?, but this requires to start off with a commit. I want to start digging with the filename.
Also is this possible without getting the whole repo locally?
After a bit of research I think I found an answer.
/*Small test*/
using (Repository repo = new Repository(strLocalDeliveryPath))
{
var fileHistory = repo.Commits.QueryBy(#"Path/To/file.ini").ToList();
int i = fileHistory.Count();
}
This is in order newest to oldest, and that suits me fine. I would normally only need the latest version of the file content, but nor i have the option of digging through the history of the file.
You can see this answer for a bit more info, but yes, the functionality was added in libgit2sharp 0.22.0. Here's an example:
var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
foreach (var version in fileHistory)
{
// Get further details by inspecting version.Commit
}

Saving WorkItem#IterationPath on newly created Iteration

I can successfully create an iteration path via:
var commonservice = collection.GetService<ICommonStructureService>();
// create new area path and iteration path
var iterationRoot = commonservice.GetNodeFromPath("\\MyTeamProject\\Iteration");
var newIterationPath = commonservice.CreateNode("my new sprint", iterationRoot.Uri);
However, when I try and assign this path to a work item and save it the field doesn't validate.
If I run the tests again (with the iteration already created) the same code succeeds.
Does anybody know how to make this work?
This fixed it for me:
WorkItemStore wis = (WorkItemStore)tfsTeamProjColl.GetService(typeof(WorkItemStore));
wis.RefreshCache();
wis.SyncToCache();
Maybe it will help someone.
I experienced exactly the same behavior, and unfortunately #JWC answer didn't help. The solution which works for me can be found by this link.
So, this is a quick summary in case the original answer gets lost.
The key point is to use WorkItemServer class. It lives in the Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll assembly.
First of all, you create a WorkItemStore instance:
var store = collection.GetService<WorkItemStore>();
Then, create necessary iteration paths:
var commonservice = collection.GetService<ICommonStructureService>();
var iterationRoot = commonservice.GetNodeFromPath("\\MyTeamProject\\Iteration");
var newIterationPath = commonservice.CreateNode("my sprint", iterationRoot.Uri);
Next, refresh the cache in TFS (I suspect this is similar to pressing F5 in web interface):
var wiServer = collection.GetService<WorkItemServer>();
wiServer.SyncExternalStructures(WorkItemServer.NewRequestId(), commonservice.GetProjectFromName("MyTeamProject").Uri);
store.RefreshCache();
And finally, assign newly created work item to the newly created iteration:
var wi = new WorkItem(store.Projects["MyTeamProject"].WorkItemTypes["Product Backlog Item"]);
wi.Title = "Hello from API";
wi.Description = "This work item was created from API";
wi.Fields["Assigned To"].Value = "Yan Sklyarenko";
wi.IterationPath = FormatPath(commonservice.GetNode(newIterationPath).Path, "Iteration", "MyTeamProject");
wi.Save();
That's it! The method FormatPath translates the iteration path to the form required by the work item IterationPath field, that is from \MyTeamProject\Iteration\my sprint to MyTeamProject\my sprint.
Hope this can save some time.
NOTE: I run this towards TFS 2013.
You are likely running into a caching issue. Try clearing the cache after you create the iteration. A couple things you could try:
Get a new copy of the WorkItemStore.
Disconnect and reconnect to TFS
Check to see if there's a "refresh" method on either the WIS or on the TFS server objects. I've shut down my dev instance of TFS for the night, and I don't recall if there's anything like it.
If that's not quite it, post your code and I'll see if I can reproduce it.
I had the similar issue. I created Areapath and then created a query where the AreaPath was used. I did call store.RefreshCashe() but it did not work. Only in Debugger when I run store.RefreshCashe() two times manually.
Thanks "Yan Sklyarenko". I tried your Suggestion and it works fine (TFS Server 2012).

Sharepoint web.config changes using SPWebConfigModification

I've written a sharepoint application that needs to change web.config
I have a feature that is supposed to make all these configurations. The code for that feature is like this:
SPSite site = properties.Feature.Parent as SPSite;
List<SPWebConfigModification> modifications = new List<SPWebConfigModification>();
modifications.AddRange(CustomErrorsModeConfig.Modifications);
webConfigModificationHelper.AddWebConfigModifications(site.WebApplication, modifications);
CustomErrorsModeConfig.Modifications property contains this code:
public static SPWebConfigModification[] Modifications = {
new SPWebConfigModification()
{
Owner = WebConfigModificationOwner,
Name = "mode",
Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute,
Path = "system.web/customErrors",
Sequence = 0,
Value = "Off"
}
};
Then finally the webConfigModificationHelper.AddWebConfigModifications method:
foreach (SPWebConfigModification modification in modifications)
{
webApp.WebConfigModifications.Add(modification);
}
webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
webApp.Update();
The problem is that I keep getting this error:
Name cannot begin with the ''' character, hexadecimal value 0x27. Line 1, position 1453
Could this be a problem with the web.config before I try to apply my changes ?
Could the SPWebConfigModification property be incorrectly defined ?
Is there some glitch in my code that leads to this error ?
Might there be some property I am missing (e.g. web.AllowUnsafeUpdates) ?
Some sharepoint site configuration ?
I've been trying to solve this issue for some time now with no luck :( Any ideas ?
I can recommend using stsadmwebconfig for making changes to web.config files. I've implemented this in many features and it has always been a pain, especially while developing. Using this tool makes it a lot easier.
Ive seen this before when the file format is not correctly set between the file and the declaration.
Open the web.config file into a advanced text editor (Notepad++ or Visual Studio) and manually force the file type to match what is specified. Usually its going to be UTF-8.
For more info:
http://www.dumpsterdoggy.com/tutorials/?xmlexception-name-cannot-begin-with
Try taking the List template and for loop out and set the property using straightforward syntax. Here's a post for setting the property in your example, see if you can get this to work and then progress to building up a more generic solution with a List and iteration over the items in the list.
http://www.sharepointkings.com/2008/05/how-to-modify-webconfig-file-in.html

Categories