如何在 Visual Studio Team Services 上成功构建后标记源
How to Label Source upon successful build on Visual Studio Team Services
我试图在 Visual Studio Team Services(不是 XAML)上使用新构建,但无法弄清楚如何在成功构建后标记源。有什么想法吗?
下面是显示如何在 XAML 中执行操作的屏幕截图。
I already have a feature request at https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/9613014-allow-label-source-upon-succesful-build-on-visual I'm actually asking for a workaround until Microsoft implements it.
标签源功能在 vNext 构建中不可用。
除了标签源功能之外,关联工作项和在构建失败时创建工作项功能也不可用。
您可以在 Microsoft UserVoice 网站上提交一项关于它的功能请求:https://visualstudio.uservoice.com/forums/121579-visual-studio/category/30925-team-foundation-server-visual-studio-online
我刚刚注意到该功能现在可以在 build vNext 中使用。它的配置位于构建定义的 Repository 选项卡中。
对于在此线程中寻找 TFS 托管(而非 VSO)解决方案的 运行,请注意,对构建标签的支持在 TFS 2015 更新 1 中出现:https://www.visualstudio.com/en-us/news/tfs2015-update1-vs.aspx
我们还没有 运行 更新 1,所以我无法确认。
编辑:我们现在是 运行 更新 1(实际上是 2),标签构建源适用于本地。
我认为 Yves Dierick 在 2015 年 10 月的回答是正确的,但从那时起 VSTS 屏幕的布局发生了很大变化。在最新版本(截至 2017 年 2 月)中,您可以通过选择构建定义中的获取源任务、选择右上角的显示 高级设置 来为成功的构建添加标签角,然后在出现的 Tag Sources 部分下选择 On success 单选按钮。
我花了一些时间才找到它,所以我认为它可能对其他人有所帮助。此选项位于 "Tag sources" 下并且根本没有提及 "label" 一词,这无济于事。
2018 年 3 月 13 日更新
他们再次调整了此页面的布局,但使其更简单,现在该选项的名称更方便 "Label Sources"。
XAML 构建在构建开始时标记源,而 vNext 构建似乎在构建结束时标记。
我注意到了,因为我在构建过程中 modify/checkin/label 文件。
如果我让 vNext 标记构建,它会在签入到以前的版本(在 GetSources 中使用的版本)后移动我应用到文件的标签。
但是我没有在任何日志文件中看到 vNext 的标签。我错过了吗?
我将不得不在 vnext 中禁用标签并在我的 msbuild 脚本中执行...
编辑:
在 vnext 构建定义中禁用标签并创建一个 msbuild 内联任务来标记工作区的源。现在我可以在构建开始时标记所有源并移动在构建期间修改的文件的标签:)
如果有人想做类似的事情,这是我的内联任务:
<!--
TaskName="LabelWorkspaceSources"
- input: TfexeFullPath is the path to tf.exe
- input: BaseDirectory is the mapped folder of the software to build
- input: Label to apply
- input: Version is the changeset to apply the label to
-->
<UsingTask TaskName="LabelWorkspaceSources" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<TfexeFullPath Required="true" />
<BaseDirectory Required="true" />
<Label Required="true" />
<Version Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
//--- get the workspace mapping ---
System.Diagnostics.Process tfProcess = new System.Diagnostics.Process();
tfProcess.StartInfo.FileName = TfexeFullPath;
tfProcess.StartInfo.Arguments = "workfold";
tfProcess.StartInfo.UseShellExecute = false;
tfProcess.StartInfo.CreateNoWindow = true;
tfProcess.StartInfo.RedirectStandardOutput = true;
tfProcess.StartInfo.WorkingDirectory = BaseDirectory;
tfProcess.Start();
string output = tfProcess.StandardOutput.ReadToEnd();
tfProcess.WaitForExit();
string workfoldOutput = output.Trim();
Log.LogMessage(workfoldOutput, MessageImportance.High);
string[] linesWorkfoldOutput = workfoldOutput.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> mappedFolders = new List<string>();
Log.LogMessage("Trying to parse mapped folders.", MessageImportance.High);
foreach (string line in linesWorkfoldOutput)
{
//e.g. $/TPA: C:\TFS_Source\TPA
if (line.Contains("$/"))
{
string[] lineSplit = line.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
//entry lineSplit[0] now contains the server path, lineSplit[1] contains the local folder
mappedFolders.Add(lineSplit[1]);
Log.LogMessage("Found mapped folder: " + lineSplit[1], MessageImportance.High);
}
}
//--- label all the mapped folders ---
foreach (string mappedFolder in mappedFolders)
{
tfProcess = new System.Diagnostics.Process();
tfProcess.StartInfo.FileName = TfexeFullPath;
tfProcess.StartInfo.Arguments = "label " + Label + " \"" + mappedFolder + "\" /child:replace /recursive /comment:\"Label created by task LabelWorkspaceSources\" /version:" + Version;
tfProcess.StartInfo.UseShellExecute = false;
tfProcess.StartInfo.CreateNoWindow = true;
tfProcess.StartInfo.RedirectStandardOutput = true;
tfProcess.StartInfo.WorkingDirectory = mappedFolder;
tfProcess.Start();
output = tfProcess.StandardOutput.ReadToEnd();
tfProcess.WaitForExit();
Log.LogMessage(tfProcess.StartInfo.Arguments, MessageImportance.High);
Log.LogMessage(output, MessageImportance.High);
}
]]>
</Code>
</Task>
</UsingTask>
我试图在 Visual Studio Team Services(不是 XAML)上使用新构建,但无法弄清楚如何在成功构建后标记源。有什么想法吗?
下面是显示如何在 XAML 中执行操作的屏幕截图。
I already have a feature request at https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/9613014-allow-label-source-upon-succesful-build-on-visual I'm actually asking for a workaround until Microsoft implements it.
标签源功能在 vNext 构建中不可用。
除了标签源功能之外,关联工作项和在构建失败时创建工作项功能也不可用。
您可以在 Microsoft UserVoice 网站上提交一项关于它的功能请求:https://visualstudio.uservoice.com/forums/121579-visual-studio/category/30925-team-foundation-server-visual-studio-online
我刚刚注意到该功能现在可以在 build vNext 中使用。它的配置位于构建定义的 Repository 选项卡中。
对于在此线程中寻找 TFS 托管(而非 VSO)解决方案的 运行,请注意,对构建标签的支持在 TFS 2015 更新 1 中出现:https://www.visualstudio.com/en-us/news/tfs2015-update1-vs.aspx
我们还没有 运行 更新 1,所以我无法确认。
编辑:我们现在是 运行 更新 1(实际上是 2),标签构建源适用于本地。
我认为 Yves Dierick 在 2015 年 10 月的回答是正确的,但从那时起 VSTS 屏幕的布局发生了很大变化。在最新版本(截至 2017 年 2 月)中,您可以通过选择构建定义中的获取源任务、选择右上角的显示 高级设置 来为成功的构建添加标签角,然后在出现的 Tag Sources 部分下选择 On success 单选按钮。
我花了一些时间才找到它,所以我认为它可能对其他人有所帮助。此选项位于 "Tag sources" 下并且根本没有提及 "label" 一词,这无济于事。
2018 年 3 月 13 日更新
他们再次调整了此页面的布局,但使其更简单,现在该选项的名称更方便 "Label Sources"。
XAML 构建在构建开始时标记源,而 vNext 构建似乎在构建结束时标记。 我注意到了,因为我在构建过程中 modify/checkin/label 文件。 如果我让 vNext 标记构建,它会在签入到以前的版本(在 GetSources 中使用的版本)后移动我应用到文件的标签。
但是我没有在任何日志文件中看到 vNext 的标签。我错过了吗? 我将不得不在 vnext 中禁用标签并在我的 msbuild 脚本中执行...
编辑: 在 vnext 构建定义中禁用标签并创建一个 msbuild 内联任务来标记工作区的源。现在我可以在构建开始时标记所有源并移动在构建期间修改的文件的标签:)
如果有人想做类似的事情,这是我的内联任务:
<!--
TaskName="LabelWorkspaceSources"
- input: TfexeFullPath is the path to tf.exe
- input: BaseDirectory is the mapped folder of the software to build
- input: Label to apply
- input: Version is the changeset to apply the label to
-->
<UsingTask TaskName="LabelWorkspaceSources" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<TfexeFullPath Required="true" />
<BaseDirectory Required="true" />
<Label Required="true" />
<Version Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
//--- get the workspace mapping ---
System.Diagnostics.Process tfProcess = new System.Diagnostics.Process();
tfProcess.StartInfo.FileName = TfexeFullPath;
tfProcess.StartInfo.Arguments = "workfold";
tfProcess.StartInfo.UseShellExecute = false;
tfProcess.StartInfo.CreateNoWindow = true;
tfProcess.StartInfo.RedirectStandardOutput = true;
tfProcess.StartInfo.WorkingDirectory = BaseDirectory;
tfProcess.Start();
string output = tfProcess.StandardOutput.ReadToEnd();
tfProcess.WaitForExit();
string workfoldOutput = output.Trim();
Log.LogMessage(workfoldOutput, MessageImportance.High);
string[] linesWorkfoldOutput = workfoldOutput.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> mappedFolders = new List<string>();
Log.LogMessage("Trying to parse mapped folders.", MessageImportance.High);
foreach (string line in linesWorkfoldOutput)
{
//e.g. $/TPA: C:\TFS_Source\TPA
if (line.Contains("$/"))
{
string[] lineSplit = line.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
//entry lineSplit[0] now contains the server path, lineSplit[1] contains the local folder
mappedFolders.Add(lineSplit[1]);
Log.LogMessage("Found mapped folder: " + lineSplit[1], MessageImportance.High);
}
}
//--- label all the mapped folders ---
foreach (string mappedFolder in mappedFolders)
{
tfProcess = new System.Diagnostics.Process();
tfProcess.StartInfo.FileName = TfexeFullPath;
tfProcess.StartInfo.Arguments = "label " + Label + " \"" + mappedFolder + "\" /child:replace /recursive /comment:\"Label created by task LabelWorkspaceSources\" /version:" + Version;
tfProcess.StartInfo.UseShellExecute = false;
tfProcess.StartInfo.CreateNoWindow = true;
tfProcess.StartInfo.RedirectStandardOutput = true;
tfProcess.StartInfo.WorkingDirectory = mappedFolder;
tfProcess.Start();
output = tfProcess.StandardOutput.ReadToEnd();
tfProcess.WaitForExit();
Log.LogMessage(tfProcess.StartInfo.Arguments, MessageImportance.High);
Log.LogMessage(output, MessageImportance.High);
}
]]>
</Code>
</Task>
</UsingTask>