【问题标题】:TFS 2015 - Delete Build ArtifactsTFS 2015 - 删除构建工件
【发布时间】:2016-06-20 21:36:49
【问题描述】:

如何升级 TFS 2015 Update 2 以在删除构建时删除工件?

这可能吗?

编辑:添加保留屏幕截图

我正在使用默认保留策略,但它不会从驱动器中删除工件。

编辑:添加复制和发布构建工件

编辑:添加工作文件夹

我添加了一个 powershell 来显示所有环境变量,它说我的 workingFolder = E:TfsBuilds\Agent1_WorkPlace\5\s

你是一个将 workingFolder 设置为默认值的 powershell 吗?

这是我的文件结构:

【问题讨论】:

    标签: tfsbuild tfs-2015


    【解决方案1】:

    如果您specify build retention policies,保留政策将删除以下项目:

    • 构建记录
    • 日志
    • 已发布的工件
    • 自动测试结果
    • 已发布的工件
    • 已发布的符号

    更多细节你可以参考类似的问题:Should artifacts associated with a build record be deleted when the build record is deleted?

    此外,如果您手动删除构建,构建的所有内容都将被删除。

    更新


    目前,删除构建时会删除服务器删除但不会删除到 UNC 共享。这也是一个已知问题:Build.Preview - Drop Folder not deleted when build is deleted

    如果是这样,您可能必须手动删除它们

    更新2


    我想知道您是否错过了带有放置文件夹的工作文件夹。默认工作文件夹位置是代理安装目录下的 _work 文件夹。此文件夹中的文件将始终保留或删除,直到触发下一次构建。您可以在构建日志中找到该目录以仔细检查。更多细节请参考MSDN的定义。


    更新3

    每个代理都有自己的工作文件夹。如 XXX\Agent1、XXX\Agent2、...XXX\Agent6。我认为问题在于您混淆了文件结构。

    使用您的文件结构,部署到服务器的文件正在复制到名为 XXX\builds 的文件夹中。但是,这些文件不是已发布的工件。有类似临时文件的东西。如果要自动删除构建下的文件,可以在最后一步添加Delete files task.。即使这些文件在构建过程中被删除。您仍然可以在构建完成后从服务器下载工件。

    【讨论】:

    • 我正在使用默认保留策略,但我没有从驱动器中删除工件。
    • 我也尝试手动删除构建,但它没有删除工件
    • 您是否将工件发布到 UNC 共享文件夹?目前,删除构建时会删除服务器删除,但不会删除到 UNC 共享。这也是一个已知问题connect.microsoft.com/VisualStudio/feedback/details/1513256/…。如果是这样,您可能必须手动删除它们。
    • 我将在辅助驱动器 E:\tfsbuilds\builds\..... .
    • 根据屏幕截图,E:\tfsbuilds\builds \...... 是 UNC 路径,UNC 文件夹也可以在构建服务器或构建代理可以连接的其他机器中。如果您选择发布到服务器,除非您使用 REST API,否则您将看不到路径。您能否分享Publish ArtifactsCopy and Publish Artifacts 步骤的屏幕截图,如果您对此不确定,
    【解决方案2】:

    我在这里做一个假设,我们知道 TFS2015 Update2 不支持开箱即用,并且 MS 声称已在 TFS15 中解决了这个问题。

    为了大家的利益,我将粘贴整个程序。这段代码有效,我正在使用它。我运行此实用程序来清理已从 TFS 中清除的构建的构建工件放置位置。我们所做的假设是,我们将使用文件夹路径这两个参数调用 exe:

    DeleteBuild.exe "D:\TFSDropLocation" "D:\DumpFolderBeforeIDeleteThis"
    

    TFSDropLocation 是 TFS 删除构建工件的位置,DumpFolderBeforeIDeleteThis 是我在永久删除之前收集所有构建的文件夹。我们本可以直接从 TFSDropLocation 中删除它们,但我喜欢这个额外的步骤,我们将它们删除到一个单独的位置,以便以防万一,我们碰巧需要它们,它们是它们的,或者从这里删除它们经过一轮验证后的位置 - 如果这让您感到舒适。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.TeamFoundation.Build.WebApi;
    using Microsoft.TeamFoundation.Core.WebApi;
    using Microsoft.VisualStudio.Services.Client;
    using System.IO;
    using System.Configuration;
    
    namespace DeleteBuild
    {
        class Program
        {
            static void Main(string[] args)
            {
                if (args.Length!=2)
                {
                    Console.WriteLine("Correct usage is: DeleteBuild.exe 'Absolute Folderpath Path to TFS drop location' 'Absolute Dump Location'");
                    Console.WriteLine("for e.g. something with quotes around the paths: DeleteBuild.exe D:\\TFSDropLocation D:\\Dumplocation");
                    return;
                }
    
                string BuildDropLocation = args[0];
                string BuildDumpLocation = args[1];
                #region TFSConnection
                string accountUrl = ConfigurationManager.AppSettings["accountUrl"];
                VssConnection connection = new VssConnection(new Uri(accountUrl), new VssAadCredential());
                ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
                TeamProject project = projectClient.GetProject(ConfigurationManager.AppSettings["TeamProject"]).Result;
                BuildHttpClient buildClient = connection.GetClient<BuildHttpClient>();
                var builds = buildClient.GetBuildsAsync(project.Id, resultFilter: BuildResult.Succeeded).Result;
                #endregion
    
                //the parent directory that is the build definition name
                DirectoryInfo directory = new DirectoryInfo(BuildDropLocation);
                // list of subdirectories which are the actual buildnumber folders
                DirectoryInfo[] ParentFolders = directory.GetDirectories();
    
                foreach (DirectoryInfo ParentFolder in ParentFolders)
                {
                    Console.WriteLine(Environment.NewLine + "Build Definition name: " + ParentFolder.Name + " contains the below mentioned builds");
                    //list of all folders inside the build definition folder which are buildnumber folders
                    DirectoryInfo[] ChildFolders = ParentFolder.GetDirectories();
                    //We evaluate each build number folder one by one
                    foreach (DirectoryInfo ChildFolder in ChildFolders)
                    {
                        Console.WriteLine(Environment.NewLine + "Evaluating folder: " + ChildFolder.Name);
                        //Create an array of builds where the definition name matches the parent foldername
                        Build[] RelevantBuilds = builds.Where(b => b.Definition.Name == ParentFolder.Name).Reverse().ToArray();
                        //set flag to false to 
                        Boolean flag = false;
                        // traverse through each build in tfs
                        foreach (Build build in RelevantBuilds)
                        {
                            {
                                //compare build number with child folder name to see if it matches
                                if (string.Compare(build.BuildNumber, ChildFolder.Name) == 0)
                                {
                                    Console.WriteLine("Found build existing, hence leaving here " + build.BuildNumber);
                                    //this build has yet not been deleted from tfs so set flag to true and traverse to the next build
                                    flag = true;
                                }
    
                            }
                        }
                        // if after travering the builds, we did not find any build that matches the foldername, flag will be set to initial value of false and this folder will be deleted
                        if (flag == false)
                        {
                            DirectoryInfo DropLocation = new DirectoryInfo(BuildDumpLocation);
                            string intermediatPath = Path.Combine(BuildDumpLocation, ParentFolder.Name);
                            DirectoryInfo IntermediateDirectory = new DirectoryInfo(intermediatPath);
                            if (!IntermediateDirectory.Exists)
                            {
                                DropLocation.CreateSubdirectory(ParentFolder.Name);
                            }
                            string sourcePath = ChildFolder.Name;
                            string targetPath = Path.Combine(DropLocation.FullName, ParentFolder.Name, ChildFolder.Name);
                            System.IO.Directory.Move(ChildFolder.FullName, targetPath);
                            Console.WriteLine("Did not find build in TFS hence moving: " + ChildFolder.Name + " to a separate dump location.");
                        }
                    }
                    Console.WriteLine("******************************************************");
                }
                Console.WriteLine("end of directory" + Environment.NewLine);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-02
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      相关资源
      最近更新 更多