开发者

Can a single TFS 2010 build definition be used for multiple branches?

I look after builds of our products and have been asked to come up with a way of customising an existing build de开发者_如何学编程finition to build different branches when required.

The build process for this product has several custom steps and actions already and the product has a large amount of project files that are built so its not effective to set up a new build definition for every new branch that is created.

The build definition is set up to build from the Main branch. The aim is to enter a particular branch (using a workflow argument that can be entered when a build is queued) which will then be built instead of the default Main branch without having to edit the build definition.

I have a separate test program that I use for testing all my custom build activities and procedures on. In the workflow for this build definition, I have added a fair few build messages for logging purposes so that I can view the values of variables used in the build process.

I have also created a branch based on this test program ready for testing of a build definition that can be used to build more than one branch

first off, I ran a build for the original test solution's project files from the original branch, then changed the build definition so that the same would be done using the new branch and ran another build. When comparing the build logs between the 2 branches there are only a few minor differences between them. (Logging Verbosity set to Diagnostic)

1st difference - I looked a the Workspace variable and the Folders property of the builds reference their respective branches, specifically the ServerItem property of the Folders property

2nd difference - The project files being built (BuildSettings.ProjectsToBuild) are coming from the respective branches

I haven't seen any other differences between the 2 build logs other than these

The main question here:

Is there a standard way of swapping the branches being built for a single build definition?

If not, would it be possible to simply change all references to the default Main branch in the customised workflow template (in Workspace and BuildSettings.ProjectsToBuild) to the entered branch when queueing a build?

As always, thanks in advance for any and all help


I have managed to amend my build's workflow template so that builds for multiple branches of the solution are possible. To achieve this I had to change certain things within the workflow and also create some extra workspaces for the service account that run the builds.

  1. I added an argument to the workflow so that the required branch can be entered when the build is queued.

  2. I changed the drop location for the build so that it is relevant for the entered branch (optional)

  3. Created a separate sources directory on the build machine for the branch build

  4. Initialised the WorkspaceName and SourcesDirectory so that they match the new workspace name and sources directory folder

  5. I created a custom activity to change the list of projects/solutions in BuildSettings.ProjectsToBuild so that they were referencing them from the entered branch

  6. I noticed through my testing phase that even though my new workspace for the entered branch was initially set up to use the entered branch as its ServerItem, it would still create the workspace with the ServerItem that was entered in the build definition. To get around this, I created another custom activity to remap the branch workspace so that the ServerItem was pointing to the correct branch

There are a few other things that I have involved in my workflow, but they are more tweaks that my developers have requested, the above steps have resulted in multiple branch builds for a single build definition.


I also wanted some more branch agility in my build definitions, so I implemented a code activity to change ProjectsToBuild (like Vermin's step 5 above). Here's the code (removed project-specific stuff):

[BuildActivity(HostEnvironmentOption.All)]
public sealed class ConvertProjectsAccordingToBranch : CodeActivity
{
    public static string s_MainBranch = "$/MyTeamProject/Main";

    public InArgument<IBuildDetail> BuildDetail { get; set; }
    public InArgument<BuildSettings> BuildSettingsOriginal { get; set; }
    public OutArgument<BuildSettings> BuildSettingsConverted { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        Logger.Instance.Init(context);
        IBuildDetail buildDetail = BuildDetail.Get(context);
        BuildSettingsConverted.Set(context, ConvertProjects(BuildSettingsOriginal.Get(context), buildDetail.BuildDefinition));
    }

    /// <summary>Returns a BuildSettings with ProjectsToBuild converted according to the build definition's workspace</summary>
    public BuildSettings ConvertProjects(BuildSettings settingsOriginal, IBuildDefinition buildDefinition)
    {
        var mappings = buildDefinition.Workspace.Mappings;
        if (mappings.Count() != 1)
        {
            throw new BuildProcessException(string.Format(CultureInfo.InvariantCulture,
                "Build definition must have exactly one workspace mapping. Build definition ID:{0} has {1} mappings",
                buildDefinition.Id,   // IBuildDefinition doesn't have any Name property, seriously!
                mappings.Count()));
        }

        string definitionBranch = mappings.First().ServerItem;
        var settingsConverted = new BuildSettings()
        {
            PlatformConfigurations = settingsOriginal.PlatformConfigurations,
        };

        foreach (string projectOriginal in settingsOriginal.ProjectsToBuild)
        {
            var projectConverted = projectOriginal.Replace(s_MainBranch, definitionBranch);
            if (!projectConverted.StartsWith(definitionBranch))
            {
                throw new BuildProcessException(string.Format(CultureInfo.InvariantCulture,
                    "Project {0} is not under main branch {1},  Definition branch: {2}",
                    projectOriginal, s_MainBranch, definitionBranch));
            }

            settingsConverted.ProjectsToBuild.Add(projectConverted);
            Logger.Instance.Log("Converted ProjectToBuild: {0},  original: {1}", projectConverted, projectOriginal);
        }

        return settingsConverted;
    }
}

I also have unit test for ConvertProjects(), but it's dependent on local stuff, so I didn't post it here. It's trivial, and definitely worth writing!


I know this is very old, but in case anybody finds this post.

We have the same requirement: Being able to build a feature branch to provide a build of a specific feature used for testing before merged to Development.

This is how we have done it:

Created a set of Visual Studio extensions:

  • Create branch build
  • Launch branch build
  • Delete branch

Create branch build will clone a build definition which are used as a template. Change the build definition name and workspace based on the branch. The build definition will be visible in Team Explorer (VS2012).

Launch branch build will find the build definition and launch the build.

Delete branch will find the build definition, delete all builds, delete the build definition, and delete the branch (Clean up). The builds and branch have a short lifetime, so it is important that these are cleaned up.


In short: No and Yes :-)

A bit more elaboration on those answers, the TFS system default templates prefer to have a single build definition for every branch you want to build, or specify all branches that need to be build at onces, but in a single build definition. There is not a standard way to choose from the available branches you have in the Queue new build dialog.

Next answer would be Yes, because indeed you can customize your build template and I understand you already started doing that. Depending on your branching structure it should be fairly easy to add a property to your template that shows up in the Queue new build dialog, and have a (for example) semi-column seperated string with all branches your want to build during a run, And for each element in that list add a solution to build in the workflow process before the template actually startes iterating that list.

That should do the job, however, I am interested in how you ended-up in wanting this ability? Are you not using VS solution files?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜