Pull to refresh
0
True Engineering
Лаборатория технологических инноваций

Разработчики в борьбе за эффективность программиста, команды, команд

Reading time 9 min
Views 8K
Всем привет.

Сегодня мы хотели бы обсудить один очень важный аспект эффективной работы — повторное использование.

Речь пойдет, конечно, о коде.

Рутинном, который не хочется писать дважды, а тем более трижды. Инфраструктурном, который приходится писать от проекта к проекту. Гениальном, который просто выражает собой отличную идею и которым грех не дать попользоваться другим.

Да и давайте признаемся — все мы любим писать “фреймворки”, которыми пользуемся потом сами и которыми пользуются другие. Это добавляет немного куража нашей повседневной деятельности.

И тут автор ловит себя на том, что поступает неправильно, начиная описывать ситуации — все и так понимают, о чем речь. А описать нужно технологии и процесс. Поэтому давайте просто остановимся на абстрактной мысли, что внезапно нашлось много кода, который может быть полезен коллегам и его хорошо бы сделать легкодоступным. Также примем во внимание вторую, куда менее приятную, мысль, что в “зрелых” проектах можно найти большое количество copy-paste кода, значительно понижающего сопровождаемость. Да и работу над такими проектами приятной назвать трудно. И с этим надо что-то делать.

И мы решили с этим что-то делать.


Путь, пройденный нами, оказался не таким сложным, мы можем посоветовать повторить его другим, ибо потраченное время себя окупает. А поскольку в какой-то момент этот путь стал интересным и даже забавным, мы решили поделиться своим опытом.

Ну да хватит предисловий.

Итак, сегодня мы в деталях расскажем:
  1. Как развернуть корпоративный nuget-сервер (основы nuget мы опустим, полагая, что большинство читателей знает, что это такое).
  2. Как развернуть корпоративный symbol-сервер, интегрированный с nuget.
  3. Почему одного nuget-сервера недостаточно для построения эффективного процесса.
  4. Также заранее обозначим темы для второй части, которую мы с удовольствием изготовим, если данная тема найдет своих читателей:
  5. Что такое SandCastle и с чем его едят.
  6. Как настроить continuous integration, чтобы автоматизировать всё нами содеянное.
  7. Несколько мыслей по поводу (само)организации.


Разворачиваем корпоративный nuget-сервер.

Итак, nuget — это здорово и весело. Это не просто новый инструмент, повышающий продуктивность, это новый подход, новый образ мыслей. Почти такой же полезный, как здоровое питание и утренняя гимнастика. Значит надо использовать.

Если речь идет о развертывании корпоративного сервера, то вариантов установки есть два:
  1. Простое развертывание ленты без UI и плюшек. Для этого варианта достаточно создать MVC application и установить сервер nuget, скачав nuget-пакет (такая вот рекурсия).
  2. Второй вариант создан для чуть менее ленивых, но зато он с UI и плюшками. Для него необходимо скачать исходники и собрать их согласно инструкции с той же страницы. После этого, нажав Ctrl+F5, мы должны увидеть (почти) полный аналог официальной ленты.




Собственно, на этом и всё — процесс чрезвычайно прост. Однако есть несколько моментов, не описанных в документации, которые проявились у нас и которые могут быть полезны другим:

1. IIS express. Вариант работы на IIS express с использованием localdb трудно рассматривать как production ready по целому ряду причин. Поэтому мы перенесли нашего новорожденного на полнофункциональный сервер IIS. Благо, сложностей с этим никаких не возникает. Просто идем во вкладку properties проекта “Website” и снимаем галку “Use IIS Express” в разделе “Web”. Visual Studio моментально среагирует на такие перемены — предложит создать Virtual Directory и сменить Connection Strings в web.config с localdb на SQL express.



2. Database Migrations. Nuget использует для доступа к данным Entity Framework и активно пользуется механизмом Database Migrations. В руководстве к развертыванию есть шаг № 4 — создание БД при помощи танцев с саблями вокруг порядка открывания вкладок в студии. На самом деле всё проще. Достаточно просто указать имя проекта, в котором хранятся migrations, при обновлении через консоль. И никаких танцев:



3. Настройки безопасности. В руководстве не описаны моменты, касающиеся настроек безопасности (хотя они были в устаревшем руководстве). Видимо, предполагается что ставит всё безоговорочный админ и крутиться всё будет под его же учеткой. Если это не так, то нам нужно:

  • a. Дать права на запись в папку “AppData” приложения. Туда будут складываться nuget-пакеты. Даем права аккаунту, под которым крутится AppPool-приложения. На случай, если в настройках IIS стоит ApplicationPoolIdentity, а не конкретная учетная запись, даем права группе IIS_IUSRS.
  • b. По тем же принципам даём права на доступ к БД в SQL.
  • c. Можно после регистрации дать себе же роль админа. Для этого после стандартной регистрации через UI вставляем запись в таблицу dbo.UserRoles, поглядев Id роли в таблице dbo.Roles. После этого по адресу “<путь к серверу>/admin” вам станет доступна админка cо всякими плюшками и букмарклетом glimpse.




4. GalleryOwner. Есть смысл поменять на реальные настройки пункта “Gallery.GalleryOwner” в web.config. От него будут рассылаться письма при регистрации. А можно и вовсе отключить эту рассылку. И обязательно пропишите актуальный SiteRoot.

<appSettings>
  <add key="Gallery.LuceneIndexLocation" value="AppData" /> 
  <add key="Gallery.Environment" value="Development" /> 
  <add key="Gallery.SiteRoot" value="http://your-server-name/" /> 
  <add key="Gallery.GalleryOwner" value="%username% <%usermail%>" /> 
  <add key="Gallery.ConfirmEmailAddresses" value="true" /> 
  <add key="Gallery.HasWorker" value="false" /> 
</appSettings>


5. В файле stats.js есть функция getStats. На момент написания данной статьи ее вызов приводил к ошибке на главной странице.



Причина кроется в том, что в локальной версии nuget статистика отключена. На данный момент она предназначена только для облачной версии.

Вы можете создать свою реализацию IStatisticsService или просто отключить данный вызов. Мы выбрали второй путь.

На этом, собственно, всё. Теперь у нас есть nuget-сервер с галереей и пакетами.

Но что, если в наш пакет (dll-ку из него) закрался баг? Или разработчик просто хочет понять, что делает наша функция “DoStuff”? Очевидно, библиотеку нужно дебажить. Но не так-то это просто, когда у нас в распоряжении есть только dll. Именно поэтому nuget умеет собирать не только пакеты библиотек, но и symbol-пакеты.

А мы идем учиться собирать свой собственный symbol server

В качестве решения для поддержки отладки мы решили использовать SymbolSource, поскольку он настолько хорошо дружит с nuget, что тот его поддерживает как symbol-сервер по умолчанию.

Тут мы сделаем небольшое отступление и расскажем, как это всё работает.

При создании nuget-пакета через команду nuget pack мы можем указать флаг “–Symbols”. В результате nuget создает, помимо стандартного пакета с библиотечкой, ещё пакет <имя_пакета>.symbols.nupkg, который будет содержать в себе pdb-файл и исходники. Потом этот пакет можно разместить на сервере SymbolSource, который проиндексирует pdb-файл и разместит у себя во внутреннем каталоге исходники проекта. Далее в Visual Studio настраивается доступ к symbol серверу, и при необходимости она загрузит с сервера pdb-файл и исходники. Так и становится возможной отладка.

Но, коли уж библиотеки мы не решились складывать в публичный feed, то про исходники и говорить нечего. В принципе, SymbolSource даёт возможность завести приватную ленту. Но также он поддерживает Community версию, позволяющую развернуть свой внутренний сервер. По целому ряду причин мы решили пойти последним путём.

И тут начались приключения…

По задумке авторов, развернуть свой symbol сервер задача почти такая же простая, как и развернуть свой nuget feed — создаем MVC-приложение, качаем nuget-пакет, даём права на папки “App_Data” и “Data” — всё работает.

Ах да, есть одно дополнительное требование — необходимо поставить Debugging Tools for Windows и прописать путь к ним в web.config:

<appSettings>
  <add key="SrcSrvPath" value="C:\Program Files\Debugging Tools for Windows (x64)\srcsrv" /> 
</appSettings>


Собственно, так мы и сделали — загрузили версию 1.3.2 SymbolServer-а, поставили, настроили, увидели волшебный экран.



Диагностику запустили — всё хорошо. Настроили Visual Studio в точности по инструкции.

Но Debug не работает…

Проблема нашлась достаточно быстро – сервис не сохранял в каталог “Data” исходники при загрузке symbol-пакета. Повозившись какое-то время с настройками IIS, мы поняли, что проблема в другом, и занялись отладкой.

Именно. Отладка сервера SymbolSource при помощи сервера SymbolSource.

Причина проблемы тоже нашлась достаточно быстро, и поначалу показалась даже смешной. В классе ManagedSourceExtractor есть метод IsTemporaryCompilerFile, возвращающий, как понятно из названия, признак, является ли некий файл временным файлом компилятора. И в этом методе стоял лишний оператор логического отрицания. То есть этот метод сообщал, что темповыми являлись как раз те файлы, которые ими не являлись. Так один лишний символ сломал весь сервер.

Ну что поделаешь… Посмеялись, форкнули исходники, поправили, собрались делать pull request. И тут мы обнаруживаем, что аналогичный request уже есть, причём создан достаточно давно. Да и пакет версии 1.3.2 выпущен уже два месяца как, а вот версия пакета с фиксом не выпущена до сих пор. Вот это уже было не так смешно. Точнее, совсем не смешно.

На какое-то время мы даже задумались, стоит ли вообще использовать этот сервер или лучше поискать другой. Но положительный предыдущий опыт использования… И разработчики nuget сделали его сервером по умолчанию, значит доверяют. И пакет версии 1.3.1 отлично работает. В итоге мы решили запустить всё на поправленных исходниках. Для этого дополнительно скопировали настройку из “Web.config.transform” в “Web.config”, поскольку при локальной сборке transform не выполняется:

<location path="WinDbg/pdbsrc">
  <system.webServer>
    <handlers>
      <clear />
      <add name="Deny" verb="*" path="*.config" type="System.Web.HttpForbiddenHandler" />
      <add name="Allow" verb="GET,HEAD" path="*" type="System.Web.StaticFileHandler" />
    </handlers>
    <security>
      <requestFiltering>
        <fileExtensions allowUnlisted="true">
          <clear />
        </fileExtensions>
      </requestFiltering>
    </security>
  </system.webServer>
</location>


Теперь готово и еще и работает как надо. И тут настало время подумать о том,

Почему одного nuget-сервера недостаточно для построения эффективного процесса (beta).

А недостаточно его по очень простой причине: nuget, как он есть, это доступный всей компании сервер.

Значит, в него нельзя класть пакеты, которые могут оказаться нестабильными. Но когда разработка конечных проектов потребовала изменения сборок, размещаемых в nuget, то внести изменения так, чтобы заработало сразу, задача из разряда “пишем код без багов”.

Различных приемов и приседаний, чтобы как-то работать с одним сервером, можно найти множество. Например, подменять ручками dll-ки в папке “packages” конечного проекта, а в nuget публиковать только когда уже всё готово. Но мы же делаем это всё, чтобы жизнь стала проще, а не наоборот. Поэтому, мы решили подойти к вопросу более обстоятельно. Немного подумав, мы придумали нечто.

Написанное ниже — это бета-версия процесса, которую мы ещё только испытываем и осмысливаем. Поэтому было бы очень здорово услышать мнения читателей в комментариях.

Итак, мы решили, что у нас будет три nuget-ленты.
  1. Local feed. На самом деле это просто сетевая папка (в Visual Studio при настройке источников можно указать не только адрес сервера, но и UNC путь к папке). В эту ленту пакеты собираются на каждый commit в VCS. Никто кроме разработчиков reusable кода source к этой ленте не настраивает.
  2. Test feed. Эта роль вполне логично ложится на сервер SymbolSource, у которого есть своя лента (именно лента, не галерея) для пакетов, куда автоматически размещается обычный nuget-пакет при публикации symbol-пакета. Публикация в эту ленту выполняется, когда закончено внесение изменений в базовый код и можно приступать к его использованию. Source к этой ленте есть у всех разработчиков компании и у build-машин, собирающих тестовые версии конечных продуктов.
  3. Сервер release-пакетов. Этим сервером стал тот, который мы развернули ещё в начале статьи — красивый, с UI и прочими плюшками. Самая важная плюшка — требование ApiKey. Локальная лента его не требует, как и лента SymbolSource (точнее SymbolSource требует, но не верифицирует). И там они и не нужны. Здесь же всё серьезнее, поэтому имеет смысл сделать так, чтобы публиковать могли не все. А если кто-то смог, было бы понятно кто это. Публикация на этот сервер идет только тогда, когда базовый код протестирован и сам по себе, и в работе с конечными продуктами. Source на данный сервер настроен у всех разработчиков, build-машин, собирающих тестовые версии конечных продуктов, build-машин, собирающих release версии конечных продуктов.

Получается, с одной стороны, что build-машины, собирающие release-версии конечных продуктов, никогда не соберут проект, если он ссылается на тестовую версию пакета.

С другой стороны, порядок того, как указаны сервера в настройках Package Sources у Visual Studio (Tools->Library Package Manager->Package Manager Settings) задает приоритет загрузки пакетов. Поэтому, например, developer-ы базового кода имеют доступ ко всем трем лентам и порядок в настройках выставлен как release feed, test feed, local feed.

В Visual Studio это выглядит это примерно вот так:



Кстати, именно тут достаточно весомым становится аргумент в пользу локального развёртывания серверов — независимость от доступа в internet и бОльшая скорость при работе в локальной сети.

“А что, если один из серверов упал?” — спросите вы. Ну, так не беда. Ведь build process “фреймворка” один на все ленты. То есть, если пакет версии 1.2.3.4 объявляется релизным, то он лежит во всех трех лентах. И доступ к нему, например, у разработчика будет всегда.

С одной стороны, такой процесс не очень прост, но с другой стороны он получился очень естественным, поэтому о его сложности задумываться придётся не часто — он просто ложится на стандартный поток работ.

Ну что же, продумали. Теперь можно вернуться к технологиям и подумать про Continuous Integration, который автоматизирует весь этот процесс.

Но статья уже затянулась.


Поэтому, будем прощаться и оставим немного материала для второй части. И тут мы хотели бы обратиться с просьбой к нашим читателям. Если тема показалась вам интересной — дайте нам это понять, оставляйте комментарии. Они помогут нам сделать вторую часть более полезной и информативной, а также мотивируют на скорейший её выпуск.

Спасибо за ваше внимание.

UPD: как оно обычно и бывает, ровно на следующий день после того, как статья была дописана, вышло обновление пакета SymbolSource.Server.Basic (версия 1.3.3), в которой исправили баг, упомянутый в разделе про развертывание symbol-сервера.
Tags:
Hubs:
+3
Comments 14
Comments Comments 14

Articles

Information

Website
www.trueengineering.ru
Registered
Founded
Employees
101–200 employees
Location
Россия