How to Move TFS 2010 Build Definition between Projects? - tfs

I have some TFS 2010 build definitions that were created under ProjectX. Now the source code has moved to a folder subordinate to ProjectY. How can I move the build definitions to ProjectY so they display under the Builds node of the Team Explorer for ProjectY?

I don't think there is something out of the box to copy the build definitions from one project to another. However you should be able to do it using the TFS API. You will want to move the build process templates, which is what Pete is referring to, into the Build Process Template folder for the new project. After that you would do something like:
var server = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("<server uri>"));
IBuildServer buildServer = server.GetService<IBuildServer>();
var buildDetails = buildServer.QueryBuildDefinitions("Project X");
foreach(var build in buildDetails)
{
var buildDefinition = buildServer.CreateBuildDefinition("Project Y");
buildDefinition.Name = "Copy of " + build.Name;
buildDefinition.BuildController = build.BuildController;
// This finds the template to use
buildDefinition.Process = buildServer.QueryProcessTemplates("Project Y")[0];
buildDefinition.ProcessParameters = build.ProcessParameters;
buildDefinition.Save();
}
A couple of things to note. You will need deal with converting the workspace mappings from one project to the other. You will also need to change the buildDefinition.Process line to find the specific template.

A powershell version of Sean's answer above
# Copy some TFS build defintions from one project collection to another
[void][Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
[void][Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.VersionControl.Client")
[void][Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Client")
$tfsUrl = "http://lontfs_at:8080/tfs/XXX"
$tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($tfsUrl)
$vcs = $tfs.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$buildServer = $tfs.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer])
$buildDetails = $buildServer.QueryBuildDefinitions("Project X");
foreach( $build in $buildDetails)
{
$buildDefinition = $buildServer.CreateBuildDefinition("Project Y");
$buildDefinition.Name = "Copy of " + $build.Name;
$buildDefinition.BuildController = $build.BuildController;
# This finds the template to use
$buildDefinition.Process = $buildServer.QueryProcessTemplates("Project Y")[0];
$buildDefinition.ProcessParameters = $build.ProcessParameters;
$buildDefinition.Save();
}

In VS2010, the TFS Power Tools can move a build definition from one project to another as demonstrated in the 2nd answer in this link: Is it possible to Export TFS 2010 Build Definitions?, and as shown below.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC>tfpt
builddefinition /collection:"http://ServerX:8080/tfs/Collection X" /clone "Project 1\Build
Definition X" "Project 2\Copy of Build Definition X"
The TFS Power Tools for VS2010 can be downloaded from: http://visualstudiogallery.msdn.microsoft.com/c255a1e4-04ba-4f68-8f4e-cd473d6b971f

Uggly but very efficient way to move (not to duplicate) only one or two Build Definitions:
Open SQL Server Management Studio,
Open your Collection DB
Edit the table tbl_BuildDefinition
Replace the current GroupId with the target Team Project's GroupId
That's it ;)
To determine the GroupId of the target Team Project, simply find any BuildDefinition of that Team Project in tbl_BuildDefinition and take its GroupId.
For sure, you have next to update the BuildDefinition's workspace, Items to build, ... to use the server path of the new Team Project !
If you get an error like "GroupItem cannot be move accross Team Project" when updating your BuildDefinition, it was most probably already open before updating the DB. Close and reopen it.
If you don't intend to repeat this operation too often, it's IMO the fastest solution.
V.

Build definitions are just another source controled file in TFS, you should be able to open the build definition in ProjectX and save it as a new file to projectY's build definitions folder.
Edit
In the above post I am assuming ProjectX and ProjectY are TFS projects, in which case their workflow build definition(s) are simply in the builddfinitions folder of their respective source control roots.

Sean's answer helped me out, but in my case, I have only one repository for my build templates and custom activities assemblies. So I don't need to edit settings, I just want to copy one build definition from TFS Project A to TFS Project B.
Here is my 'short' version of Sean's code:
var server = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("TFS URL"));
IBuildServer buildServer = server.GetService<IBuildServer>();
var buildDetails = buildServer.QueryBuildDefinitions("Proj_A");
foreach(var build in buildDetails)
{
var buildDefinition = buildServer.CreateBuildDefinition("Proj_B");
buildDefinition.CopyFrom(build);
buildDefinition.Save();
}

Related

Calling Another Project's Controller From A Project In The Same Solution (.NET Core )

There are 2 projects in the same solution. First project is a .NET Core project and it has all the codes(controllers, models etc.) related to packages. I need to get the information (id, name, description) of the packages and display it in the second project(.NET Core Web App with Razor). Is it possible to do it without changing the first project? I only want to show the package list on a single web page.
I tried calling the first project's controller but it didn't work. Maybe I missed a point. Any help is appreciated.
This requirement can be achieved, please see the gif image below.
Tips
If you want to call another project's controller from a project in the same solution, you need to make sure there is in HomeController in both project. I mean the name of any class should be unique in both projects.
Otherwise you will face the same issue like my homepage.
Test Code:
public List<PackageReference> GetPackageList5(string projectname)
{
List<PackageReference> list = new List<PackageReference>();
PackageReference p = null;
XDocument doc = XDocument.Load(_webHostEnvironment.ContentRootPath+ "/"+ projectname + ".csproj");
var packageReferences = doc.XPathSelectElements("//PackageReference")
.Select(pr => new PackageReference
{
Include = pr.Attribute("Include").Value,
Version = pr.Attribute("Version").Value
});
Console.WriteLine($"Project file contains {packageReferences.Count()} package references:");
foreach (var packageReference in packageReferences)
{
p = new PackageReference();
p.Version= packageReference.Version;
p.Include= packageReference.Include;
list.Add(packageReference);
//Console.WriteLine($"{packageReference.Include}, version {packageReference.Version}");
}
return list;
}
My Test Steps:
create two project, Net5MVC,Net6MVC
add project reference.
My .net6 project references a .net5 project. So in my HomeController (.net), I add below:
using Net5MVC.ForCore6;
using Net5MVC.Models;
Suggestion
When we reference the .net5 project in .net6 project, we can build success, but when we deploy it, it always failed. The reason is some file was multiple publish output files with the same relative path.
Found multiple publish output files with the same relative path:
D:\..\Net6\Net6\Net5MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net6MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net5MVC\appsettings.json,
D:\..\Net6\Net6\Net6MVC\appsettings.json.
And usually will add class library to current project, not add a web project.
As we know we can find packages info in .csproj file, so we need copy and paste .csproj file to publish folder.
I still recommend using the GetPackageList5 method above as an interface for your project, using HttpClient for requests.

Find XML file changes in all branches

I have an XML file in my main TFS branch. I have 50 branches of the main folder. Is there a quick way to check in which branches the file is modified before merging it to the main branch?
I have found that it can be done with CodeLens for code files, but I don't know how to do it for XML files.
You can refer to these steps below:
Create a new workspace
Map these branches (Do not include other mapping)
To do work (e.g. modify files)
Open Team Explorer
Switch to this workspace
Click Pending Changes, then all changes in this workspace will be list.
If these changes are already existing in different workspace, you can check in changes through TFS API (install Microsoft Team Foundation Server Extended Client package to your project).
Simple code to iterate all workspaces in a machine and check in specified changes:
NetworkCredential cred = new NetworkCredential("[username]", "[password]", "[domain]");
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("[collection url"), cred);
tpc.EnsureAuthenticated();
VersionControlServer versionControl = tpc.GetService<VersionControlServer>();
var spaces = versionControl.QueryWorkspaces(null, null, "[machine name, can be null]");
foreach(var currentWorkspace in spaces)
{
var libChanges= currentWorkspace.GetPendingChanges("[server or local path]",RecursionType.Full);
if (libChanges.Count() > 0)
{
currentWorkspace.CheckIn(changes: libChanges, comment: "checkInAPI");
}
}
Update:
You can compare branches.
Open Source Control Explorer
Right click a branch > Compare
Change Target path to target branch server path
Click OK.
On the other hand, there is an TFS Productivity Pack extension you can use.

How can I create a directory in my source control using TFS 2010 SDK?

I want to customize the creation of a TFS project using TFS 2010 SDK.
I have already create a process template and use this sample, but I want to create a specific directory tree for the new team project base on a XML file which describe the tree. My problem is this message; The array must contain at least one element.
Parameter name: checkinParameters.PendingChanges
I initialize the TFS, map the server folder with a local folder and create directories in both.
fooString = Array.Find<WorkingFolder>(workspace.Folders, m => m.ServerItem.Contains("$/FR_DEV"));
Directory.CreateDirectory(ElementPath);
Directory.CreateDirectory(fooString.ServerItem + ElementTfsPath);
After that:
PendingChange[] PendingChanges = workspace.GetPendingChanges();
// Checkin the items we added
int changesetForAdd = workspace.CheckIn(PendingChanges, "Project creation.");
However, I get an error for the pending change! How can I fix this?
my problem was that i need to add the directory in the workspace not with a simple path
workspace.PendAdd(currentSubDirectory, true);

How do you SetMaxAttachmentSize in TFS 2010?

I want to set the maximum work item attachment size. From old blogs I have found that it is possible by calling SetMaxAttachmentSize, but the blogs are for older versions of TFS. I have found the new webservice path for TFS 2010.
http://localhost:8080/tfs/_tfs_resources/WorkItemTracking/v1.0/ConfigurationSettingsService.asmx/SetMaxAttachmentSize
Unfortunately when I call it like that I receive this error: This request can only be made against a project collection. The (.asmx) file should be located in the project directory (usually _tfs_resources under the application root).
I don't know how to format the call via a browser to target a specific project collection. Any thoughts?
Apparently SetMaxAttachmentSize web service was not leveraged on TFS 2010 therefore you need to do this programmatically, try running the following code:
TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(#"http://yourtfsserver:8080/tfs/DefaultCollection");
ITeamFoundationRegistry rw = tfs.GetService<ITeamFoundationRegistry>();
RegistryEntryCollection rc = rw.ReadEntries(#"/Service/WorkItemTracking/Settings/MaxAttachmentSize");
RegistryEntry re = new RegistryEntry(#"/Service/WorkItemTracking/Settings/MaxAttachmentSize", "20971520"); //20MB
if (rc.Count != 0)
{
re = rc.First();
re.Value = "20971520";
}
rw.WriteEntries(new List<RegistryEntry>() { re });
I hope it works for you
Regards,
Randall Rosales
I have found that this works. It is easier than writing code.
Go to this url replacing <Collection> with your project collection: http://localhost:8080/tfs/<Collection>/WorkItemTracking/v1.0/ConfigurationSettingsService.asmx
Choose SetMaxAttachmentSize
You can test to make sure you set it correctly by going to the same url above and then selecting GetMaxAttachmentSize.

Delphi: How to set the default project in a project group?

i have two projects in a project group:
ProjectA
ProjectB
Whenever i open the ProjectGroup.bpg in Delphi, it always starts with the 2nd project as the active one:
ProjectA
ProjectB
And every time i have to flip it to the the "real" project:
ProjectA
ProjectB
How can i make ProjectA the default project that opens with the project group?
ProjectGroup.bpg
#------------------------------------------------------------------------------
VERSION = BWS.01
#------------------------------------------------------------------------------
!ifndef ROOT
ROOT = $(MAKEDIR)\..
!endif
#------------------------------------------------------------------------------
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
DCC = $(ROOT)\bin\dcc32.exe $**
BRCC = $(ROOT)\bin\brcc32.exe $**
#------------------------------------------------------------------------------
PROJECTS = ProjectA.exe ProjectB.exe
#------------------------------------------------------------------------------
default: $(PROJECTS)
#------------------------------------------------------------------------------
ProjectA.exe: ProjectA.dpr
$(DCC)
ProjectB.exe: childfolder\ProjectB.dpr
$(DCC)
See DUnit: How to run unit tests for the practical reason.
Far from ideal but the only way I know is like
in the Delphi IDE, right click your default project in the Project Manager and select Build Later.
or Switch the lines for Project A and Project B in the .bpg file.
You might have a stuck desktop settings file. Look for a .DSK file associated with your project group, and delete it.
In Delphi 7 (and I presume later also) you can select the 'active' project in the project group tree by double-clicking it. If you then do 'Save Project Group As' by right clicking the top of the project tree, the active project is saved with the group and will open at that when you next open the project group.
Place file ProjectGroup.dsk in project folder with text:
[ActiveProject]
ActiveProject=1
or set check to TRUE in Environment Options -> Preferences -> Autosave Options -> Project Desktop, this will create DSK files for projects and groups automatic!

Resources