Подтвердить что ты не робот

Преобразование конфигурации триггера в TFS 2010 или msbuild

Я пытаюсь использовать преобразования конфигурации в непрерывной среде интеграции.

Мне нужен способ сообщить агенту сборки TFS выполнить преобразования. Я как бы надеялся, что это сработает только после обнаружения файлов конфигурации config (web.qa-release.config, web.production-release.config и т.д.). Но это не так.

У меня есть определение сборки TFS, которое строит правильные конфигурации (qa-release, production-release и т.д.), и у меня есть некоторые определенные .proj файлы, которые создаются внутри этих определений, и те, которые содержат некоторые специфические для среды параметры, например

<PropertyGroup Condition=" '$(Configuration)'=='production-release' ">
    <TargetHost Condition=" '$(TargetHost)'=='' ">qa.web</TargetHost>
    ...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)'=='qa-release' ">
    <TargetHost Condition=" '$(TargetHost)'=='' ">production.web</TargetHost>
    ...
</PropertyGroup>

Я знаю из вывода, что строятся правильные конфигурации. Теперь мне просто нужно научиться запускать конфигурационные преобразования. Есть ли какой-то hocus pocus, который я могу добавить в финальный .proj в сборке, чтобы начать преобразование и сдуть отдельные файлы преобразования?

4b9b3361

Ответ 1

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

  • Перейти к Team Explorer > Builds
  • Отредактируйте определение сборки (или создайте новое)
  • На шаге "Процесс" есть настройки "Конфигурации для сборки".

В моем случае я настроил конфигурацию специально для CI, которая затем выполняет правильные преобразования web.config. Убедитесь, что вы добавили файл преобразования "CI", и вам должно быть хорошо идти.

Ответ 2

Я нашел другой способ выполнить это вместо создания пользовательской активности. Вам просто нужно изменить файл проекта визуальной студии создаваемого веб-приложения.

Добавьте следующее (местозаполнитель для цели "AfterBuild" можно найти в конце файла проекта):

<Target Name="AfterBuild" Condition="$(IsAutoBuild)=='True'"> 
  <ItemGroup> 
         <DeleteAfterBuild Include="$(WebProjectOutputDir)\Web.*.config" /> 
  </ItemGroup> 
  <TransformXml Source="Web.config" Transform="$(ProjectConfigTransformFileName)" Destination="$(WebProjectOutputDir)\Web.config"/> 
  <Delete Files="@(DeleteAfterBuild)" />
</Target> 

Затем вам просто нужно добавить /p:IsAutoBuild="True" в поле "Аргументы MSBuild", которое находится в разделе "Дополнительно" определения сборки.

Это заставит TFS 2010 делать преобразования в файле web.config, когда TFS делает сборку.

Более подробную информацию можно найти на Блог Кевина Дейли.

Ответ 3

Мне, наконец, удалось заставить это работать. Я использую TFS 2008, но также использую MSBuild 4.0, поэтому он должен работать для вас.

Сначала добавьте этот импорт в TFSBuild.proj:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Затем добавьте цель BeforeDropBuild:

<Target Name="BeforeDropBuild">
  <TransformXml Source="$(SolutionRoot)\MySite\Web.config"
    Transform="$(SolutionRoot)\MySite\Web.QA.config"
    Destination="$(OutDir)\_PublishedWebsites\MySite\Web.QA.config.transformed" />
</Target>

Затем вы можете скопировать файл Web.QA.config.transformed туда, куда вам нужно.

Ответ 4

Функциональность преобразования web.config, добавленная в проекты веб-сайта в Visual Studio 2010, по умолчанию отключена для команд командной строки и TFS.

Существуют два относительно простых решения:

Вариант 1: отредактируйте определение сборки и добавьте следующее в поле "Аргументы MSBuild":

/p:UseWPP_CopyWebApplication=true /p:PipelineDependsOnBuild=false

UseWPP_CopyWebApplication приведет к активации нового веб-публикации (WPP) для сборки. WPP выполняет преобразования web.config и также может быть использован для блокировки таких файлов .PDB, которые будут скопированы в папку bin.

Вариант 2. Оба MSBuild и WPP полностью расширяемы. Создайте новый XML файл в том же каталоге, что и ваш проект, и используйте расширение ".targets" - например, ProjectName.custom.targets. Поместите следующий код MSBuild в файл целей:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <UseWPP_CopyWebApplication>True</UseWPP_CopyWebApplication>
    <PipelineDependsOnBuild>False</PipelineDependsOnBuild>
  </PropertyGroup>
</Project>

Щелкните правой кнопкой мыши на своем веб-сайте и выберите "Выгрузить проект". Щелкните правой кнопкой мыши на выгруженном проекте и выберите "Изменить". Выделите нижнюю часть файла проекта и найдите следующие строки:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Эти строки связаны с подключением процесса сборки С# и Web Project. Вставьте импорт в свои пользовательские расширения сборки (целевой файл) непосредственно перед импортом CSharp:

<Import Project="ProjectName.custom.targets"/>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Что ты... тебе хорошо. Метод настройки MSBuild - это немного больше работы по настройке, но преимущество заключается в том, что вы можете использовать новый файл целей, чтобы "подключиться" к процессу сборки и иметь гораздо больший контроль над тем, как ваша сборка происходит на сервере. Например, можно выполнить задачи для сжатия CSS и JS.

Я также рекомендую посмотреть "цели wpp" - если вы назовете другой файл MSBuild с определенным именем "ProjectName.wpp.targets", вы сможете контролировать весь процесс публикации веб-сайта. Мы используем его для удаления файлов документации javascript -vsdoc по мере копирования опубликованного выхода на веб-сайт:

<ItemGroup>
  <ExcludeFromPackageFiles Include="Scripts\**\*-vsdoc.js;Resources\Scripts\**\-vsdoc.js">
    <FromTarget>Project</FromTarget>
  </ExcludeFromPackageFiles>
</ItemGroup>

Все сказанное, вам, вероятно, лучше отказаться от производства web.configs из вашей сборки полностью. Мы размещаем трансформации непосредственно на нашей производственной машине развертывания и используем powershell для преобразования при развертывании приложения.

Ответ 5

Вот вам более простой ответ.:)

http://social.msdn.microsoft.com/Forums/en-US/tfsbuild/thread/d5c6cc7b-fbb1-4299-a8af-ef602bad8898/

Из ссылки (в случае ее перемещения/404/и т.д.):

Вот как я решил это. Ключ было отредактировать файл *.csproj на веб-сайта и добавить Цель AfterBuild (обязательно переместите конец комментария выше). Это для проект нашего сайта в Team Foundation Server.

<Target Name="AfterBuild">
    <TransformXml Condition="Exists('$(OutDir)\_PublishedWebsites\$(TargetName)')"
                  Source="Web.config"
                  Transform="$(ProjectConfigTransformFileName)"
                  Destination="$(OutDir)\_PublishedWebsites\$(TargetName)\Web.config" />
</Target>

Чтобы сохранить файл web.debug.config, web.release.config и т.д.... из не забудьте установить "Build Действие" в окне свойств для каждое преобразование конфигурации файлов на "Нет". Только основные web.config должен иметь "Build Действие" в разделе "Содержание"

Один простой способ редактировать файл csproj - загрузить либо "PowerCommands" для Visual Studio 2010 "или Расширение" Производительность электроинструмента "к Visual Studio 2010, доступной из Галерея Visual Studio. однажды загружено все, что вам нужно сделать, это правильно нажмите на проект в своем решении и выберите" Выгрузить проект ". Затем вы щелкните правой кнопкой мыши и выберите" Изменить... "для редактирования файла csproj XML непосредственно. Тогда, когда все сделано правильно нажмите еще раз и выберите" Перезагрузка Проект".

Ответ 6

Чтобы сделать это в WorkFlow, вам нужно создать пользовательскую активность. Там довольно хорошая статья об этом здесь

Для этого конкретного действия вам необходимо создать проект Activity (изменить его из .Net 4 Client profile на .Net 4) и ссылку Microsoft.Build.Framework и Microsoft.Build. Utilities.v4.0 из GAC, а затем Microsoft.Web.Publishing.Tasks из% programfiles%\msbuild\Microsoft\VisualStudio\v10.0\WebApplications (% programfiles (x86) %, если вы используете 64-битную систему).

Когда это будет сделано, вы добавите эти два класса:

Во-первых, там заглушка:

internal class BuildEngineStub : IBuildEngine
{
    public bool BuildProjectFile(string projectFileName, string[] targetNames, System.Collections.IDictionary globalProperties, System.Collections.IDictionary targetOutputs)
    {
        throw new NotImplementedException();
    }

    public int ColumnNumberOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }

    public bool ContinueOnError
    {
        get { throw new NotImplementedException(); }
    }

    public int LineNumberOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }

    public void LogCustomEvent(CustomBuildEventArgs e)
    {
    }

    public void LogErrorEvent(BuildErrorEventArgs e)
    {
    }

    public void LogMessageEvent(BuildMessageEventArgs e)
    {
    }

    public void LogWarningEvent(BuildWarningEventArgs e)
    {
    }

    public string ProjectFileOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }
}

Тогда класс активности сам:

[BuildActivity(HostEnvironmentOption.Agent)]
public sealed class WebConfigTransform : CodeActivity
{
    private const string WEB_CONFIG = "Web.config";
    private const string WEB_CONFIG_TRANSFORM_FORMAT = "Web.{0}.config";

    private IBuildEngine _buildEngine { get { return new BuildEngineStub(); } }

    [RequiredArgument]
    public InArgument<string> TransformationName { get; set; }
    [RequiredArgument]
    public InArgument<string> SourceFolder { get; set; }
    [RequiredArgument]
    public InArgument<string> DestinationFolder { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        var transformationName = context.GetValue(this.TransformationName);
        var sourceFolder = context.GetValue(this.SourceFolder);
        var destinationFolder = context.GetValue(this.DestinationFolder);

        var source = Path.Combine(sourceFolder, WEB_CONFIG);
        var destination = Path.Combine(destinationFolder, WEB_CONFIG);
        var destinationbackup = string.Format("{0}.bak", destination);
        var transform = Path.Combine(sourceFolder, string.Format(WEB_CONFIG_TRANSFORM_FORMAT, transformationName));

        if(!File.Exists(source))
            throw new ArgumentException("Web.config file doesn't exist in SourceFolder");
        if (!File.Exists(transform))
            throw new ArgumentException("Web.config transformation doesn't exist in SourceFolder");
        if (File.Exists(destination))
        {
            File.Copy(destination, destinationbackup);
            File.Delete(destination);
        }

        var transformation = new TransformXml();
        transformation.Source = new TaskItem(source);
        transformation.Destination = new TaskItem(destination);
        transformation.Transform = new TaskItem(transform);
        transformation.BuildEngine = _buildEngine;

        if (transformation.Execute())
        {
            File.Delete(destinationbackup);
        }
        else
        {
            File.Copy(destinationbackup, destination);
            File.Delete(destinationbackup);
        }
    }
}

Причиной для BuildEngineStub является то, что класс TransformXml использует его для ведения журнала.

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