Как мне использовать Nuget для внутреннего развития предприятия?
Мы используем Nuget для нашей внутренней разработки, чтобы позволить нам обмениваться кодом между командами. Однако мы сталкиваемся с проблемами, когда один человек работает над кодом, который будет развернут в нескольких пакетах nuget одновременно. Например
А зависит от В, который зависит от С.
A, B и C отправляют свои артефакты в Nuget, и именно так мы управляем зависимостями между A, B и C. Проблема, которую мы обнаруживаем, заключается в том, что если разработчик хочет внести изменения в C и быстро увидеть эти изменения, отраженные в A, они должны пройти через следующий процесс.
- Внести изменения в C.
- Нажмите изменить до мерзавца
- CI регистрирует изменения в C, создает и развертывает новый пакет nuget.
- Войдите в B и обновите ссылку на C, используя команду пакета обновлений nuget.
- Вставьте изменения в файл packages.config до git
- CI принимает изменения в B и создает и развертывает новый пакет nuget для B
- Теперь откройте A и измените ссылку на B и пакет обновлений nuget
- Внесите изменения в A, чтобы согласиться с изменениями в B(и транзитивно C)
Это кажется чрезвычайно болезненным и заставляет некоторых наших разработчиков усомниться в выборе Nuget для нашего внутреннего кода. Всем до сих пор нравится это для потребления внешних пакетов.
Есть ли лучший рабочий процесс для внутреннего использования Nuget?
4 ответа
В нашей компании мы решили проблему каскадных обновлений с помощью следующей настройки. Сначала у нас есть следующая настройка для наших репозиториев NuGet и сервера сборки.
- Существует внутренний репозиторий NuGet, который содержит все опубликованные пакеты для компании. Этот репозиторий является просто общим каталогом на одном из наших серверов.
Каждый разработчик может иметь (но не обязан иметь) один или несколько каталогов на своем компьютере, которые служат локальным хранилищем пакетов NuGet. Используя пользовательскую конфигурацию NuGet, разработчик может контролировать, в каком порядке NuGet выполняет поиск в репозиториях пакетов, чтобы найти пакеты.
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageRestore> <add key="enabled" value="True" /> </packageRestore> <packageSources> <add key="Dev" value="D:\dev\testpackages" /> <add key="Company" value="<UNC_ADDRESS_COMPANY_REPOSITORY>" /> <add key="NuGet official package source" value="https://nuget.org/api/v2/" /> </packageSources> <disabledPackageSources /> <activePackageSource> <add key="All" value="(Aggregate source)" /> </activePackageSource> </configuration>
Во всех решениях включено автоматическое восстановление пакетов, поэтому нам не нужно фиксировать пакеты в нашей системе контроля версий.
- Разработчики контролируют только 3 из 4 номеров версий, например, если версия
<MAJOR>.<MINOR>.<BUILD>.<REVISION>
тогда разработчики могут изменять только основной, вспомогательный и сборочный номера, номер редакции устанавливается равным 0, за исключением сборок, выполняемых сервером сборки, где это номер сборки сборки. Это важно, потому что это означает, что для данной версии, состоящей из основного, вспомогательного номера и номера сборки, сервер сборки всегда будет выпускать более высокий номер версии. Это снова означает, что NuGet предпочтет взять версию пакета, поступающую из репозитория пакетов компании (который получает пакеты только через сервер сборки).
Для внесения изменений в одну из базовых библиотек используются два возможных процесса. Первый процесс:
- Сделайте изменения в базовой библиотеке (A). Обновите версию (A) при необходимости.
- Запустите сценарий MsBuild, чтобы собрать двоичные файлы и создать пакеты NuGet из (A)
- Скопируйте новые пакеты NuGet в хранилище пакетов на локальном компьютере.
- В зависимом проекте (B) обновите до новых пакетов (A), которые были только что помещены в хранилище пакетов локального компьютера (версия должна быть более высокой, чем те, которые доступны в общедоступном хранилище компании, или NuGet.org)
- Сделайте изменения в (B).
Если для (A) требуются дополнительные изменения, повторите шаги 1, 2 и 3, а затем удалите пакет (A) из рабочего каталога (B). В следующий раз, когда будет запущена сборка, NuGet будет искать конкретную версию (A), найти ее в репозитории локального компьютера и вытащить ее обратно. Обратите внимание, что кеш NuGet может иногда мешать этому процессу, хотя выглядит как NuGet может не кэшировать пакеты, которые приходят с одного компьютера (?).
После внесения изменений мы:
- Зафиксируйте изменения в (A). Сервер сборки запустит интеграционную сборку, чтобы убедиться, что все работает.
- Скажите серверу сборки запустить сборку выпуска, которая собирает двоичные файлы и отправляет пакеты NuGet в репозиторий NuGet в масштабах всей компании.
- В (B) обновите до последней версии (A) (которая должна иметь более высокий номер версии, чем тестовый пакет, потому что тестовый пакет должен иметь версию abc0, в то время как новая версия сборки в репозитории всей компании должна быть abc, где> 0
- Зафиксируйте изменения в (B). Подождите, пока сервер сборки завершит интеграционные тесты
- Скажите серверу сборки, чтобы он выполнил сборку релиза (B).
Еще один способ сделать работу по разработке, сделав следующие шаги
- Сделайте изменения в базовой библиотеке (A). Обновите версию (A), если требуется.
- Построить двоичные файлы
- Скопируйте двоичные файлы в место, где NuGet распаковывает пакет (A) для проекта (B) (например,
c:\mysource\projectB\packages\ProjectA.1.2.3.4
) - Сделайте необходимые изменения в проекте (B)
Процесс фиксации остается тем же, сначала необходимо зафиксировать проект (A), а в проекте (B) ссылку NuGet на (A) необходимо обновить.
Первый подход немного более аккуратен, поскольку этот процесс также предупреждает о наличии ошибок в пакете NuGet (A) (например, забыл добавить новую сборку), в то время как во втором процессе разработчик не узнает об этом после пакета для (A).) был опубликован.
У вас есть два варианта здесь:
- Запустите экземпляр галереи NuGet в вашей организации. Это код, который запускает nuget.org
- Получите лицензию на Artifactory Pro, которая имеет встроенную поддержку Nuget и действует как репозиторий Nuget.
Я использовал оба варианта, и № 1 - разумный выбор для начала, но NuGet Galley оптимизирован и предназначен для nuget.org, а не для локального / корпоративного использования, поэтому такие вещи, как удаление пакетов, являются трудной задачей (требуется ручной SQL).
Я бы сказал, что вы должны заплатить (низкую) лицензионную плату за Artifactory Pro - это отличный продукт, и команда JFrog действительно заинтересована и включена.
Вы не должны использовать nuget.org для внутренних / корпоративных пакетов; nuget.org предназначен для сторонних библиотек / библиотек с открытым исходным кодом, а не для внутренних зависимостей сборки.
РЕДАКТИРОВАТЬ: с точки зрения рабочего процесса, почему вы помещаете общий код в несколько пакетов? Если необходимо предоставить общий доступ к коду, он должен находиться в отдельном пакете.
РЕДАКТИРОВАТЬ 2: Чтобы ускорить рабочий процесс изменения кода для разработчика, вы можете использовать nuget.exe
(клиент командной строки) и используйте доступные из командной строки сборки, так что вы можете выбрать целевой запуск для разработчика. Затем в вашей сборке "разработчика" (в отличие от сборки CI) вы указываете -Source как локальный путь (например, nuget install B -Source C:\Code\B
) когда хочется вытащить недавно обновленный B
как зависимость и строить против этого; аналогично для C
или другие локальные, недавно обновленные пакеты. Тогда, когда A
, B
, а также C
все хорошо построить можно git push
все они (в обратном порядке зависимости), и пусть CI делает свое дело.
Тем не менее, вам также следует задаться вопросом, действительно ли разделение вашего пакета действительно уместно, если вам приходится часто делать эту сборку "танцем", поскольку это предполагает, что весь код должен быть в одном пакете или, возможно, разделен по разным строкам в отдельных пакетах. Ключевой особенностью четко определенного пакета является то, что он не должен вызывать волновых эффектов в других пакетах, особенно если вы не используете Semantic Versioning эффективно.
Редактировать 3 Некоторые пояснения, запрошенные marcelo-oliveira: "доступные из командной строки сборки" - это сборки, которые могут выполняться полностью из командной строки, без использования Visual Studio, обычно через пакетные файлы. "Сборка разработчика" - это сборка, которую разработчик запускает со своей рабочей станции, в отличие от сборки CI, которая выполняется на сервере CI (обе сборки по сути должны быть одинаковыми).
Если A, B и C находятся под одним и тем же решением, вы можете создать пакеты NuGet для них в одной сборке.
Просто убедитесь, что в используемом пакете есть новый номер версии (при условии, что ваша сборка не меняет его случайно) пакета, от которого он зависит.
Если A, B и C преднамеренно используют разные решения, например, A относится к инфраструктурному решению, а B - к продукту, то единственное, что я могу предложить, - определить, какие сборки CI запускаются при регистрации, а не периодически.
Редактировать:
Другим вариантом является создание пакетов предварительного выпуска (например, версия 1.0.0-alpha) на вашем сервере NuGet во время локальных сборок. Таким образом, разработчики могут поэкспериментировать с пакетом до создания версии выпуска.
Nuget был разработан для совместного использования сторонних библиотек. Мы планируем использовать Nuget для всего общего кода, который может быть разделен между проектами. Такие вещи, как общий слой данных, строки и другие функции регулярных выражений, компоненты электронной почты и другие подобные артефакты.
Единственный способ, которым я вижу Nuget - это помощь, когда компоненты, код или артефакты, которыми вы делитесь между командами / проектами, стабильны и имеют свой собственный цикл выпуска, который отличается от цикла выпуска вашего проекта. Для ваших нужд Nuget - это излишество. Вы можете повысить производительность, связывая все такие проекты в одном решении. Структура вашего решения должна включать три проекта A,B и C как зависимые проекты, на которые есть ссылки, когда это необходимо.