В этой записи я попробую рассказать, как можно доставить любой файловый контент, включенный (автоматически или вручную) в ваш солюшен автоматически, один и только один раз. Для примера буду использовать umbraco и платные модули Seochecker и Contour. Причину, по которой это может понадобиться я опишу далее.
Самый простой способ установить Umbraco в солюшен – это использовать Nuget пакет. Всё ставится, нужные файлы раскладываются по нужным местам, и, что немаловажно, при помощи UmbracoCMS.targets файла из пакета во время сборки в пакет для доставки добавляются все папки Umbraco. Как мне кажется, отличное решение, позволяющее иметь чистое дерево в солюшене и в то же время – доставлять весь необходимый файловый контент на удаленный сервер. Всё отлично до тех пор, пока в Umbraco нет как минимум двух вышеупомянутых модулей: Seochecker и Contour.
Seochecker позволяет проводить автоматическую валидацию seo, проверять битые ссылки и добавлять редиректы. Почему этот модуль является проблемным с точки зрения доставки? Потому что, в отличии от остальных модулей, его конфигурация хранится не в базе данных, на файловой системе в папке ~/Umbraco/Plugins/SEOChecker/Config, которая будет автоматически включена в пакет для доставки файлом UmbracoCMS.targets. Таким образом, локальная конфигурация SEOChecker будет доставлена на удаленный сервер, что приведёт к некорректным sitemap.xml и robots.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, которая заставит msdeploy пропустить операцию Update (обновление) для указанных файлов и папок
- UseMsDeployExe заставляет билд процесс использовать MsDeploy.exe, а не провайдер из Visual Studio (в провайдере, как указано на Stackoverflow есть баг, не позволяющий контролировать файловые операции.
После данной модификации файлы Seochecker из папки config и файлы форм из ~/App_Plugins/UmbracoForms/Data будут доставлены на целевой сервер лишь один раз. Далее, файлы автоматически обновляться не будут. Впрочем, если из удалить на сервере - то MsDeploy позаботиться о том, чтобы доставить их заново.