TFS Build не преобразует web.config, как ожидалось
Цель состоит в том, чтобы создавать и развертывать TFS 2+ разных конфигураций, а файлы преобразования web.config включают в себя предназначенный контент в своем выпуске. Это в проекте ASP.NET MVC.
![alt text]()
Web.Debug.Config - см. в PasteBin.
Web.Release.Config - см. В PasteBin
У 2 преобразованных конфигурационных файлов установлено значение Build Action равным None. Это было изменено, поскольку в развертывание включены все 3 файла конфигурации. *. Config.
TFS правильно настроена для создания и развертывания обеих конфигураций. Он разворачивается в 2 места падения, как ожидалось. Аргументы MSBuild не определены в определении сборки.
![alt text]()
Проблема. 2 встроенных и развернутых веб-сайта имеют один и тот же файл web.config. В основном это как будто преобразованные файлы не существовали.
Ожидаемый: указанные изменения (xdt:Transform="Replace"
и xdt:Transform="Remove"
) будут присутствовать в файлах web.config.
Как вы можете настроить свой проект или TFS для обеспечения преобразования преобразований web.config, а их выходы развернуты в правильные места развертывания? Что еще я могу проверить/изменить?
- Подтвердили, что преобразования хороши - Учебник Vishal Joshit с MSBuild в командной строке выводит правильные преобразования!
- Никаких изменений в .csproj для каких-либо пост-сборки или развертывания не было.
- Используются ли какие-либо атрибуты
xdt
неправильно или отсутствуют?
- В определении сборки отсутствуют аргументы MSBuild.
- Правильно ли установлены правила сборки Web.config?
- Мы не используем пакеты веб-развертывания или что-то еще. Просто ожидая xcopy этих выходов к их различным местоположениям веб-серверов позднее.
Если мне не хватает какой-либо важной информации, оставьте комментарий, и я включу любую более важную информацию!
Ответы
Ответ 1
Раньше я делал что-то похожее на другие ответы. Тем не менее, я просто нашел то, что кажется лучшим решением этой проблемы. Просто добавьте "/p: UseWPP_CopyWebApplication = true/p: PipelineDependsOnBuild = false" к вашим аргументам MSBuild. Я просто попробовал это на одной из моих сборников TFS, и все работает отлично.
Я нашел этот замечательный совет здесь: http://www.andygeldman.com/index.php/2011/10/web-and-app-config-transformations-with-tfs-build.
Ответ 2
Команда TFS Team Build 2010 автоматически не преобразует ваши Web.configs. Чтобы выполнить это, вам нужно добавить пользовательский рабочий процесс к шаблону процесса сборки.
У Эдвальда Хофмана есть хороший блог, в котором объясняется, как изменить TFS 2010 Build Process Templates, поэтому я не буду углубляться в это.
http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx
После того, как вы выясните, как добавить пользовательские действия к шаблону процесса сборки, добавьте в свой рабочий процесс следующие действия. Я добавил активность после "Drop Plles to Drop Location". Он использует сборку Microsoft.Web.Publishing.Tasks(расположенную: C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web
) для выполнения преобразований:
/// <summary>
/// Transforms configuration files using TransformXml
/// </summary>
[BuildActivity(HostEnvironmentOption.All)]
public sealed class WebConfigTransform : CodeActivity
{
#region Public Properties
/// <summary>
/// The binaries folder
/// </summary>
[RequiredArgument]
public InArgument<string> BinariesLocation { get; set; }
#endregion
#region Overrides of CodeActivity
/// <summary>
/// When implemented in a derived class, performs the execution of the activity.
/// </summary>
/// <param name="context">The execution context under which the activity executes.</param>
protected override void Execute(CodeActivityContext context)
{
var binariesFolder = context.GetValue(BinariesLocation);
foreach (var sourceFolder in Directory.GetDirectories(Path.Combine(binariesFolder, "_PublishedWebsites")))
{
var sourceFile = Path.Combine(sourceFolder, "Web.config");
if (File.Exists(sourceFile))
{
var filesToTransform = Directory.GetFiles(sourceFolder, "Web.*.config");
foreach (var fileToTransform in filesToTransform)
{
var tempSourceFile = Path.GetTempFileName();
var tempTransformFile = Path.GetTempFileName();
File.Copy(sourceFile, tempSourceFile, true);
File.Copy(fileToTransform, tempTransformFile, true);
var transformation = new TransformXml
{
BuildEngine = new BuildEngineStub(),
Source = tempSourceFile,
Transform = tempTransformFile,
Destination = fileToTransform
};
transformation.Execute();
}
}
}
}
#endregion
}
Вам нужно будет передать это droplocation в рабочий поток. Когда вы добавите его в рабочий поток, щелкните правой кнопкой мыши на активности, затем перейдите к свойствам и вставьте "DropLocation" (выражение VB) в свойство "BinaryLocation"
ПРИМЕЧАНИЕ. Вам необходимо создать класс BuildEngineStub, который реализует интерфейс IBuildEngine, чтобы использовать задачу MSBuild. Вот что я использовал
public class BuildEngineStub : IBuildEngine
{
#region IBuildEngine Members
public bool BuildProjectFile(string projectFileName, string[] targetNames,
IDictionary globalProperties,
IDictionary targetOutputs)
{
throw new NotImplementedException();
}
public int ColumnNumberOfTaskNode
{
get { return 0; }
}
public bool ContinueOnError
{
get { return false; }
}
public int LineNumberOfTaskNode
{
get { return 0; }
}
public string ProjectFileOfTaskNode
{
get { return ""; }
}
public void LogCustomEvent(CustomBuildEventArgs e)
{
Console.WriteLine("Custom: {0}", e.Message);
}
public void LogErrorEvent(BuildErrorEventArgs e)
{
Console.WriteLine("Error: {0}", e.Message);
}
public void LogMessageEvent(BuildMessageEventArgs e)
{
Console.WriteLine("Message: {0}", e.Message);
}
public void LogWarningEvent(BuildWarningEventArgs e)
{
Console.WriteLine("Warning: {0}", e.Message);
}
#endregion
}
Ответ 3
Вот что я использовал. Текущая задача TransformXml имеет ошибку, при которой файлы остаются открытыми. Подробнее здесь.
Вы можете вызвать эту задачу и развернуть для каждой конфигурации, с которой работаете.
<Target Name="TransformWebConfig">
<PropertyGroup>
<_tempSourceFile>$([System.IO.Path]::GetTempFileName())</_tempSourceFile>
<_tempTransformFile>$([System.IO.Path]::GetTempFileName())</_tempTransformFile>
</PropertyGroup>
<Copy SourceFiles="$(_websiteDirectory)\Web.config" DestinationFiles="$(_tempSourceFile)"/>
<Copy SourceFiles="$(_websiteDirectory)\Web.$(_transformConfiguration).config" DestinationFiles="$(_tempTransformFile)"/>
<MSBuild.Community.Tasks.Attrib Files="$(_websiteDirectory)\Web.config" ReadOnly="false" />
<TransformXml Source="$(_tempSourceFile)"
Transform="$(_tempTransformFile)"
Destination="$(_websiteDirectory)\Web.config"
StackTrace="false" />
</Target>
Ответ 4
Падение фактически не преобразуется. Вам нужно добавить /p:DeployOnBuild=True
в аргументы MSBuild.
Это создаст пакет, который затем можно будет использовать для установки веб-сайта либо через командную строку, либо с помощью мастера импорта приложений IIS.
Если вам нужно опубликовать более чем одну конфигурацию, это целая другая история, и именно так я наткнулся на этот пост.
Ответ 5
Попытайтесь не устанавливать платформу сборки - в основном удалить "Любой процессор" в ItemToBuild и выбрать платформу MSBuild как "Авто"