Click here to Skip to main content
15,891,597 members
Articles / Programming Languages / XML

Generate Automated Builds for Source Code from Multiple Branches using Team Foundation Server and Team Builds

Rate me:
Please Sign up or sign in to vote.
4.83/5 (29 votes)
14 Mar 2010CPOL3 min read 64.6K   537   50  
Generate automated builds for source code from multiple branches using Team Foundation Server and Team Builds
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
//using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualStudio.TeamFoundation.VersionControl;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using System.IO;

namespace Suresh.TeamFoundation.Addins
{
    public partial class SprintCleanupForm : Form
    {
        private VersionControlExplorerExt SourceControlExplorer = null;
        private static string SourceServerPath = string.Empty;

        private TeamFoundationServer tfsServer;
        private TeamProject teamProject;
        //private VersionControlServer vcs;
        private IBuildServer buildServer;

        public SprintCleanupForm(VersionControlExplorerExt vce)
        {
            SourceControlExplorer = vce;
            InitializeComponent();
        }

        private void SprintCleanupForm_Load(object sender, EventArgs e)
        {
            VersionControlExplorerItem vceItem = SourceControlExplorer.SelectedItems[0];
            SourceServerPath = vceItem.SourceServerPath;
            lblSelectedNode.Text = SourceServerPath;

            tfsServer = SourceControlExplorer.Workspace.VersionControlServer.TeamFoundationServer;
            teamProject = SourceControlExplorer.Workspace.VersionControlServer.GetTeamProjectForServerPath(SourceControlExplorer.SelectedItems[0].SourceServerPath);
            //vcs = tfsServer.GetService(typeof(VersionControlServer)) as VersionControlServer;
            buildServer = tfsServer.GetService(typeof(IBuildServer)) as IBuildServer;
        }

        private void btnAction_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            try
            {
                PerformUserDefinedAction();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception caught while performing the action: " + ex);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void PerformUserDefinedAction()
        {
            List<string> buildDefinitionIDsToDelete = new List<string>();
            if (chkBldDefns.Checked)
                DeleteBuildDefns(buildDefinitionIDsToDelete);

            if (chkCode.Checked)
            {
                bool isFolderAlreadyMapped = SprintSetupForm.EnsureTeamProjectIsMapped(SourceControlExplorer.Workspace, SourceServerPath, teamProject.ServerItem);
                DeleteCode();

                if (!isFolderAlreadyMapped)
                    SprintSetupForm.DeleteTemporaryWorkspace(SourceControlExplorer.Workspace, teamProject.ServerItem);
            }

            if(chkBldDefns.Checked)
                WorkOnGeneralCleanup(buildDefinitionIDsToDelete);

            MessageBox.Show("Action performed successfully, this form will be closed now.");
            this.Close();
        }

        private void WorkOnGeneralCleanup(List<string> buildDefinitionIDsToDelete)
        {
            string buildDefinitionIDs = String.Empty;
            if (buildDefinitionIDsToDelete.Count > 0)
                buildDefinitionIDs = String.Join(",", buildDefinitionIDsToDelete.ToArray());

            QueueCleanupBuild(buildDefinitionIDs);
        }

        private void QueueCleanupBuild(string buildDefinitionIDs)
        {
            string branchFolderPath = SourceServerPath.Replace(teamProject.ServerItem + "/", "");
            branchFolderPath = branchFolderPath.Replace("/", @"\");

            IBuildDefinition cleanupBuildDefinition = buildServer.GetBuildDefinition(teamProject.Name, MainCleanupBuildDefinitionName);
            IBuildRequest cleanupBuildRequest = cleanupBuildDefinition.CreateBuildRequest();
            cleanupBuildRequest.CommandLineArguments = "/p:prmBranchFolder=" + branchFolderPath;
            if (!String.IsNullOrEmpty(buildDefinitionIDs))
                cleanupBuildRequest.CommandLineArguments += ";prmBuildDefinitionIdsToDelete=\"" + buildDefinitionIDs + "\"";
            buildServer.QueueBuild(cleanupBuildRequest);
        }

        private static string MainCleanupBuildDefinitionName
        {
            get
            {
                return "Main.Cleanup.Pinned";
            }
        }

        private void DeleteCode()
        {
            Workspace workspace = SourceControlExplorer.Workspace;

            try
            {
                workspace.Get(new GetRequest(SourceServerPath, RecursionType.OneLevel, VersionSpec.Latest), GetOptions.GetAll | GetOptions.Overwrite);
            }
            catch (MissingMethodException) { }

            try
            {
                workspace.PendDelete(SourceServerPath, RecursionType.Full);
            }
            catch (MissingMethodException) { }

            CheckinPendingChanges(workspace);
        }

        private static void CheckinPendingChanges(Workspace workspace)
        {
            PendingChange[] pendingChanges = workspace.GetPendingChanges(SourceServerPath, RecursionType.Full);
            if (pendingChanges.Length > 0)
            {
                PolicyOverrideInfo policyOverrideInfo = new PolicyOverrideInfo("Overriden policy - deleted by code of Sprint cleanup addin", null);
                try
                {
                    workspace.CheckIn(pendingChanges, "Deleted by Sprint Cleanup Addin", null, null, policyOverrideInfo);
                }
                catch (MissingMethodException) { }
            }
        }

        private void StopAliveBuilds(IBuildDefinition buildDefinition, IQueuedBuildSpec queuedBuildSpecification)
        {
            bool isBuildsStatusChanged = true;
            while (isBuildsStatusChanged)
            {
                isBuildsStatusChanged = false;
                IQueuedBuildQueryResult queuedBuildQueryResult = buildServer.QueryQueuedBuilds(queuedBuildSpecification);
                IQueuedBuild[] queuedBuilds = queuedBuildQueryResult.QueuedBuilds;
                foreach (IQueuedBuild queuedBuild in queuedBuilds)
                {
                    if (queuedBuild.BuildDefinition.Name == buildDefinition.Name)
                    {
                        if (queuedBuild.Status == QueueStatus.Postponed || queuedBuild.Status == QueueStatus.Queued)
                        {
                            queuedBuild.Cancel();
                            isBuildsStatusChanged = true;
                        }
                        else if (queuedBuild.Status == QueueStatus.InProgress)
                        {
                            if (queuedBuild.Build != null)
                                queuedBuild.Build.Stop();
                            isBuildsStatusChanged = true;
                        }
                        break;
                    }
                }
            }
        }

        private void DoDeletion(List<IBuildDefinition> buildDefinitionsToDelete, IQueuedBuildSpec queuedBuildSpecification, List<string> dropLocationPaths)
        {
            foreach (IBuildDefinition buildDefinition in buildDefinitionsToDelete)
            {
                StopAliveBuilds(buildDefinition, queuedBuildSpecification);

                IBuildDetail[] buildDetails = buildDefinition.QueryBuilds();
                foreach (IBuildDetail buildDetail in buildDetails)
                {
                    if (buildDetail.Status == BuildStatus.InProgress)
                        buildDetail.Stop();
                    buildDetail.Delete();
                }

                try
                {
                    dropLocationPaths.Add(buildDefinition.DefaultDropLocation);
                    buildDefinition.Delete();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Build Definition delete failed - " + ex);
                }
            }
        }

        private void DeleteBuildDefns(List<string> buildDefinitionIDsToDelete)
        {
            List<IBuildDefinition> buildDefinitionsToDelete = new List<IBuildDefinition>();

            IBuildDefinition[] allBuildDefinitions = buildServer.QueryBuildDefinitions(teamProject.Name);
            foreach (IBuildDefinition buildDefinition in allBuildDefinitions)
            {
                if ((buildDefinition.ConfigurationFolderPath + "/").StartsWith(SourceServerPath + "/", StringComparison.OrdinalIgnoreCase))
                {
                    buildDefinitionsToDelete.Add(buildDefinition);
                    if(buildDefinition.Uri.Segments.Length > 0)
                        buildDefinitionIDsToDelete.Add(buildDefinition.Uri.Segments[buildDefinition.Uri.Segments.Length - 1]);
                }
            }

            List<string> dropLocationPaths = new List<string>();
            IQueuedBuildSpec queuedBuildSpecification = buildServer.CreateBuildQueueSpec(teamProject.Name);
            queuedBuildSpecification.QueryOptions = QueryOptions.Definitions;
            queuedBuildSpecification.Status = QueueStatus.All;

            DoDeletion(buildDefinitionsToDelete, queuedBuildSpecification, dropLocationPaths);

            DeleteDropLocations(dropLocationPaths, teamProject.ServerItem);
        }

        private static void DeleteDropLocations(List<string> dropLocationPaths, string teamProjectServerItem)
        {
            //foreach (string dropPath in dropLocationPaths)
            //{
            //    if (Directory.Exists(dropPath))
            //        Directory.Delete(dropPath, true);
            //}

            string rootDropFolder = SprintSetupForm.GetSpecificFolderName(SourceServerPath, teamProjectServerItem);
            if (dropLocationPaths.Count > 0)
            {
                int index = dropLocationPaths[0].LastIndexOf(rootDropFolder, StringComparison.OrdinalIgnoreCase);
                if (index > 0)
                {
                   string dropFolder = dropLocationPaths[0].Substring(0, index + rootDropFolder.Length);
                   if (Directory.Exists(dropFolder))
                       Directory.Delete(dropFolder, true);
                }
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void grpBoxAction_Enter(object sender, EventArgs e)
        {

        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer PROTEANS SOFTWARE SOLUTIONS LTD.(www.proteans.com)
India India
I am currently working in an outsourced software product development company, PROTEANS SOFTWARE SOLUTIONS LTD.(www.proteans.com) as a Module Lead.

Comments and Discussions