TFS Build не преобразует web.config, как ожидалось

Цель состоит в том, чтобы TFS собирала и развертывала более 2 различных конфигураций, а файлы преобразования web.config включали в свои выходные данные предполагаемый контент. Это в проекте ASP.NET MVC.

альтернативный текст

Web.Debug.Config - см. На PasteBin.
Web.Release.Config - см. На PasteBin

Для 2 преобразованных файлов конфигурации их действие сборки установлено на "Нет". Это было изменено, потому что все 3 файла web.*. Config были включены в развертывание.

TFS настроен правильно для построения и развертывания обеих конфигураций. Он разворачивается в 2 места сброса, как и ожидалось. В определении сборки не указаны аргументы MSBuild.

альтернативный текст

Проблема: 2 встроенных и развернутых веб-сайта имеют один и тот же файл web.config. По сути, это как если бы преобразованные файлы не существовали.

Ожидаемые: указанные изменения (xdt:Transform="Replace" а также xdt:Transform="Remove") будет присутствовать в файлах web.config.

Как вы можете сконфигурировать свой проект или TFS, чтобы обеспечить обработку преобразований web.config и развертывание их выходных данных в правильных местах развертывания? Что еще я могу проверить / изменить?

  • Подтвердили, что преобразования хороши - учебник Джошита Вишала с MSBuild в командной строке выдает правильные преобразования!
  • В.csproj не было внесено никаких изменений для пост-сборки или развертывания.
  • Есть какие-нибудь xdt атрибуты используются неправильно или отсутствуют?
  • В определении сборки не указаны аргументы MSBuild.
  • Правильно ли настроены действия по сборке web.config?
  • Мы не используем пакеты веб-развертывания или что-то еще. Просто ожидаем, что позже скопируем эти результаты в их различные местоположения веб-сервера.

Если мне не хватает какой-либо важной информации, пожалуйста, оставьте комментарий, и я добавлю любую более важную информацию!

5 ответов

Ранее я делал что-то похожее на другие ответы. Тем не менее, я только что нашел лучшее решение этой проблемы. Просто добавьте "/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.

TFS Team Build 2010 не преобразует автоматически ваши Web.configs. Для этого необходимо добавить настраиваемое действие рабочего процесса в шаблон процесса сборки.

Эдвальд Хофман (Edwald Hofman) имеет хороший блог, в котором объясняется, как модифицировать шаблоны процессов сборки TFS 2010, поэтому я не буду подробно останавливаться на этом здесь.

http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx

После того, как вы выяснили, как добавить пользовательские действия в шаблон процесса сборки, добавьте следующее действие в рабочий процесс, я добавил действие после "Перенести файлы в папку размещения". Он использует сборку 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 Expression) в свойство "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
    }

Вот что я использовал. В текущей задаче 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>

Старайтесь не устанавливать платформу сборки - просто удалите "Любой процессор" в ItemToBuild и выберите платформу MSBuild как "Авто"

Падение на самом деле не делает никакого преобразования. Что вам нужно, это добавить /p:DeployOnBuild=Trueк аргументам MSBuild.

Это создаст пакет, который затем можно будет использовать для установки веб-сайта либо с помощью командной строки, либо с помощью мастера импорта приложений IIS.

Если вам нужно напрямую опубликовать более одной конфигурации, которая является совершенно другой историей, и именно так я наткнулся на этот пост.

Другие вопросы по тегам