Перейти к содержимому

MsDeploy: как доставить файловый контент лишь один раз для солюшена

В этой записи я попробую рассказать, как можно доставить любой файловый контент, включенный (автоматически или вручную) в ваш солюшен автоматически, один и только один раз. Для примера буду использовать и платные модули Seochecker и Contour. Причину, по орой это может понадобиться я опишу далее.

Самый простой способ установить Umbraco в солюшен – это использовать Nuget пакет. Всё ставится, нужные файлы раскладываются по нужным местам, и, что немаловажно, при помощи UmbracoCMS.targets файла из пакета во время сборки в пакет для доставки добавляются все папки Umbraco. Как мне кажется, отличное решение, позволяющее иметь чистое дерево в солюшене и в то же время – доставлять весь необходимый файловый контент на удаленный сервер. Всё отлично до тех пор, пока в Umbraco нет как минимум двух вышеупомянутых модулей: Seochecker и Contour.
Seochecker позволяет проводить автоматическую валидацию , проверять битые ссылки и добавлять редиректы. Почему этот модуль является проблемным с точки зрения доставки? Потому что, в отличии от остальных модулей, его конфигурация хранится не в базе данных, на файловой системе в папке ~/Umbraco/Plugins/SEOChecker/Config, которая будет автоматически включена в пакет для доставки файлом UmbracoCMS.targets. Таким образом, локальная конфигурация SEOChecker будет доставлена на удаленный сервер, что приведёт к некорректным sitemap.xml и .txt, как минимум. Конечно же есть выход – использовать SlowCheetah плагин и трансформировать конфигурационный файл для каждого сервера, но тут нас поджидает другая проблема: Seochecker.config может редактироваться из Umbraco клиента, что позволяет контент-менеджеру управлять им. А контент-менеджеры, за редким исключением, как правило, быстро забывают о том, что они сделали. Потому они легко забудут об изменениях в SEOChecker, но после доставки они сразу же прибегут жаловаться на то, что изменения потерялись.

С модулем Contour (данный модуль позволяет контент-менеджерам создавать и управлять формами на веб приложении) задача схожая – он устанавливается в ~/App_plugins/UmbracoForms и, что самое неудобное, сериализует данные о созданных формах в ~/App_plugins/UmbracoForms/Data. Представьте себе ситуации, когда вы создали в локальной среде форму, доставили ее на «боевой» сервер, а там уже контент менеджер привнёс в нее какие-либо изменения – поле добавил/удалил, цели изменил или ещё что-либо сделал. После доставки – эти изменения пропадут.

Для того, чтобы не наступать на эти грабли, необходимо незначительно модифицировать проект добавив в него следующий XML-код (до закрывающего тега /Project):

<PropertyGroup>
    <OnBeforePackageUsingManifest>
        $(OnBeforePackageUsingManifest);
        AddSpecificSkipRule;
    </OnBeforePackageUsingManifest>
    <AfterAddIisSettingAndFileContentsToSourceManifest>
        $(AfterAddIisSettingAndFileContentsToSourceManifest);
        AddSpecificSkipRule;
    </AfterAddIisSettingAndFileContentsToSourceManifest>    
    <!-- Due to known error (http://stackoverflow.com/questions/12576662/msdeploy-skip-rules-when-using-msbuild-publishprofile-with-visual-studio-2012)
    we should use MsDeployExe for delivery, if we want to skip only several folders  
    And as we are skipping SeoChecker.config update - we shall use it always-->
    <UseMsDeployExe>true</UseMsDeployExe>
</PropertyGroup>
    <Target Name="AddSpecificSkipRule" >
    <ItemGroup>
          <MsDeploySkipRules Include="SkipUpdateSeoChecker">
            <SkipAction>Update</SkipAction>
            <ObjectName>dirPath</ObjectName>
            <AbsolutePath>Umbraco/Plugins/SEOChecker/Config</AbsolutePath>
            <XPath>
            </XPath>
          </MsDeploySkipRules>
          <MsDeploySkipRules Include="SkipUpdateSeoCheckerConfig">
            <SkipAction>Update</SkipAction>
            <ObjectName>filePath</ObjectName>
            <AbsolutePath>Umbraco/Plugins/SEOChecker/Config/SEOChecker\.config$</AbsolutePath>
            <XPath>
            </XPath>
          </MsDeploySkipRules>
          <MsDeploySkipRules Include="SkipUpdateSeoCheckerConfig">
            <SkipAction>Update</SkipAction>
            <ObjectName>filePath</ObjectName>
            <AbsolutePath>Umbraco\\Plugins\\SEOChecker\\Config\\SEOChecker\.config$</AbsolutePath>
            <XPath>
            </XPath>
          </MsDeploySkipRules>
          <MsDeploySkipRules Include="SkipUpdateContourForms">
            <SkipAction>Update</SkipAction>
            <ObjectName>filePath</ObjectName>
            <AbsolutePath>App_Plugins\\UmbracoForms\\Data\\.*$</AbsolutePath>
            <XPath>
            </XPath>
          </MsDeploySkipRules>          
    </ItemGroup>
</Target>

Далее я расскажу, что и зачем добавлено.

  • OnBeforePackageUsingManifest и AfterAddIisSettingAndFileContentsToSourceManifest контролируют каким образом создаётся пакет для доставки. Тут мы добавляем дополнительную встроенную цель AddSpecificSkipRule, которая заставит пропустить операцию Update (обновление) для указанных файлов и папок
  • UseMsDeployExe заставляет билд процесс использовать MsDeploy.exe, а не провайдер из Visual Studio (в провайдере, как указано на Stackoverflow есть баг, не позволяющий контролировать файловые операции.

После данной модификации файлы Seochecker из папки config и файлы форм из ~/App_Plugins/UmbracoForms/Data будут доставлены на целевой сервер лишь один раз. Далее, файлы автоматически обновляться не будут. Впрочем, если из удалить на сервере - то MsDeploy позаботиться о том, чтобы доставить их заново.