С помощью Git Workflows, NPM и сторонних библиотек

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

В этой статье я объясню, как объединить рабочий процесс git, semver и NPM для создания правильного управления библиотеками и CI в JavaScript. Меня это начало беспокоить, когда моя команда стала больше, и нам пришлось создать лучший процесс, который работал бы для всех и о чем мы договорились. Я прочитал около 20 статей, чтобы составить это тщательно продуманное объединенное резюме различных практик и официальных рекомендаций.

GIT FLOW

Есть разные шаблоны использования Git. Шаблоны определяют, какие типы веток будут существовать в проекте, их соглашения об именах, когда использовать каждый тип и так далее. Самый известный шаблон - Git Flow.

GitFlow похож на Agile - все используют его какую-то версию.

Он был создан в январе 2010 года компанией Винсент Дриссен. С тех пор он активно использовался, хотя его много критиковали. Я подробно остановлюсь на их точке зрения после объяснения самой методологии.

Я настоятельно рекомендую прочитать его полностью и использовать приведенное ниже резюме только в качестве шпаргалки (он также содержит некоторые дополнительные идеи).

Два типа ветвей

Бесконечные ветки времени жизни: master и develop

  • origin / master всегда готов к производству.
  • origin / develop всегда включает последние внесенные изменения для следующего выпуска. Когда он готов, он объединяется в мастер, и изменения помечаются номером версии.

Филиалы с ограниченным сроком службы

  • Ветви функций
  • Отпустите ветки
  • Исправления веток

Давайте рассмотрим каждый из них более подробно.

Филиалы функций

  • Отделился от develop и снова слился с ним.
  • Соглашение об именах: все, кроме master, develop, release- * или hotfix- *. Я люблю использовать префикс feature/, например feature/fix-texts.

При обратном слиянии в develop Винсент рекомендует использовать флаг —-no-ff, который всегда создает новую фиксацию для слияния. Это позволяет вам лучше понимать отслеживание истории и знать, какие коммиты были выпущены вместе, как функция. Это также упрощает возврат функции.

Отрасли выпуска

  • Отделился от develop и снова слился с develop и master.
  • Соглашение об именах: release- *, например: release-1.2.
  • Цель: небольшие изменения в последнюю минуту, чтобы было ясно, что разработка получит изменения для следующего выпуска.

До разветвления ветки выпуска изменения для следующего выпуска нельзя объединить в develop. Номер версии определяется при создании ветки выпуска и используется в качестве ее имени.

npm-версия

После создания ветки выпуска вы должны запустить ./bump-version.sh. Это вымышленный сценарий, обновляющий номер версии проекта. Как я уже упоминал, статья Git Flow написана в январе 2010 года. Это также месяц, когда NPM был впервые выпущен (совпадение ??), и я предпочитаю использовать npm-версию, как показано ниже:

> npm version patch

На выходе будет номер новой версии. В ветку будет добавлена ​​фиксация с обновлением новой версии в файлах package.json и package-lock.json.

Запустите git log -1, а затем git show <commit hash>, чтобы увидеть изменения.

Для изменения дополнительной версии или основной используйте npm version minor или npm version major соответственно.

Используйте флаг -m, чтобы добавить сообщение о фиксации, иначе это будет номер новой версии.

Если preversion, version, или postversion указаны в свойстве scripts файла package.json - они также будут выполнены.

Он также создаст тег git. Вы можете убедиться в этом, запустив git tag до и после запуска npm version patch, и заметите разницу.

Как объясняется в документации по тегу git, по умолчанию команда git push не передает теги на удаленные серверы. Вам нужно будет явно отправить теги на общий сервер после того, как вы их создали. Этот процесс похож на совместное использование удаленных веток. Вы можете запустить git push origin v1.5.1. Также можно удалять и извлекать локальные и удаленные теги.

Альтернативой npm-version является популярный инструмент release-it, который может повышать версию, создавать теги и выпуски и многое другое.

Вернуться к выпуску филиалов

Итак, вы создали ветку выпуска, запустили npm version patch и нажали. Возможно, вы также добавили мелкие исправления ошибок. Следующим шагом будет слияние с мастером и выпуском.

Создание релиза из тега

Как объясняется в документации GitHub, при создании релиза вам необходимо ввести для него номер версии. Версии основаны на тегах Git. Под областью ввода версии вы увидите текст: Выберите существующий тег или создайте новый тег при публикации. Вы можете выбрать, следует ли отправлять тег, созданный npm-version, а затем ввести его снова при создании выпуска, или вы можете не отправлять его и ввести его при создании выпуска. Конечно, вы можете создать автоматический релиз вместо того, чтобы вручную использовать сайт GitHub.

Слить обратно в разработку

Не забудьте снова объединить ветку выпуска для разработки. Затем ветку релиза можно удалить. Здесь могут возникнуть конфликты слияния, поэтому просто исправьте их и выполните фиксацию.

Ветви исправлений

  • Содержат исправления для срочных производственных ошибок.
  • Отделился от master и снова слился с develop и master.
  • Соглашение об именах: hotfix-*.

Как и ветки релиза, они предназначены для подготовки к новому релизу, и процесс создания ветки и завершения ее полностью идентичен.

Если вы работаете с ветвями выпуска и существует ветвь выпуска, старайтесь не объединять ее обратно для разработки, а с веткой выпуска, которая будет объединена в разработку позже.

Это так?

Это способ Git Flow. Это будет лучше работать с методологией водопада. Рекомендуемый сегодня способ работы - это непрерывное развертывание - быть полностью покрытым тестами, не иметь ветки develop, объединить функциональные ветки для мастеринга и немедленного развертывания.

Но тип продукта и рынок могут иногда диктовать другой тип процесса развертывания. Например, в здравоохранении не всегда возможно непрерывное развертывание из-за нормативных требований. В игровой индустрии есть даты выпуска игр, и они часто не работают с непрерывной интеграцией и доставкой.

ОППОНЕНЕЦ

Если вы поищете в Google «не используйте gitflow», то найдете множество статей. Вот основные моменты некоторых из них:

#1

В своем блоге End Of Line Адам Рука заявляет, что использование флага --no-ff приводит к git train maps (см. Фото), которые очень трудно отследить. в ретроспективе. Он настоятельно рекомендует вместо этого использовать rebase.

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

Хотя я согласен с первым пунктом, я думаю, что автоматизация сборки (например, автоматическая маркировка) и хорошо настроенные ветки на GitHub могут решить большинство человеческих ошибок. В этой статье он предлагает другой взгляд на Git Flow.

#2

В своей статье Git: как я использую и почему я не использую GitFlow Мэтью ДеКрей говорит о ветке develop:

«Наличие кода в общем месте, где он не полностью протестирован и не обязательно работает над функцией, которая должна быть выпущена, в конечном итоге превращается в город-призрак с недоработанными архитектурами и невыпущенными функциями, если команда когда-либо будет занята».

Я думаю, что при некоторой дисциплине и приличном CI команда объединит (или перебазирует) только develop функции, которые готовы и прошли модульные тесты и интеграционные тесты, а затем ночной тестовый костюм (или системные тесты) может запускаться при разработке и убедитесь, что функции работают вместе.

Другая проблема, о которой он упоминает, - это поддержка старых версий: «после того, как вы вырежете выпуск v1.2, вы больше не сможете патчить v1.1». И в этой статье вы также можете найти его рекомендуемый способ работы с ветками Git.

#3

В своей статье Рабочие процессы GitHub внутри компании Николас Закас говорит:

«По общему мнению, git-flow хорошо работает для продуктов с более традиционной моделью выпуска, где выпуски делаются раз в несколько недель, но этот процесс значительно нарушается, когда вы выпускаете один раз в день или чаще» .

Спустя полтора года после публикации Git Flow Скотт Чакон, инженер, который помог запустить GitHub, опубликовал GitHub flow, более простую версию Git Flow, которая лучше работает с проектами компакт-дисков.

ЧТО ТОГДА ВЫБРАТЬ?

Одна из проблем, с которыми мы сталкиваемся сегодня в отрасли, - это борьба с представлением о том, что есть только один способ делать все правильно. Мы игнорируем тот факт, что разные команды, продукты и рынки требуют разных решений.

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

«Помните, что эти рабочие процессы разработаны как рекомендации, а не конкретные правила. Мы хотим показать вам, что возможно, чтобы вы могли комбинировать и сочетать аспекты из разных рабочих процессов в соответствии с вашими индивидуальными потребностями. При оценке рабочего процесса вашей команды очень важно учитывать корпоративную культуру ».

Позже добавляют:

«Универсального рабочего процесса Git не существует. Важно разработать рабочий процесс Git, который повысит продуктивность вашей команды. Помимо командной культуры, рабочий процесс также должен дополнять бизнес-культуру. Такие функции Git, как ветки и теги, должны дополнять график выпуска релизов вашего бизнеса ».

Они рекомендуют работать с недолговечными ветвями и стремиться минимизировать и упростить откаты.

Squashed коммитирует или нет?

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

Теперь, когда я обучился здоровому подходу, описанному в упомянутой выше статье об Atlassian, я думаю, что это сильно зависит от проекта. Для проектов с открытым исходным кодом, с большим количеством удаленных участников, лучше раздавить, чтобы сохранить видение проекта на высоком уровне.

Для стабильных организаций, в которых хотя бы часть команды продолжает работать над проектом в любой момент, лучше разработать и сохранить небольшие коммиты, но только при соблюдении двух условий:

  1. С ориентировочными сообщениями, а не «стереть», «исправить» и т. Д.
  2. Каждая фиксация сама по себе не нарушает сборку или продукт, т. Е. Если функция содержит 3 фиксации и мы отменяем 2 из них, продукт стабилен и работает хорошо.

СЕМВЕР

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

Идея состоит в том, что каждый новый выпуск будет иметь номер версии в форме x.y.z, например: 1.1.2. X увеличивается, когда отсутствует основная версия, т. Е. Когда API не работает. Y - второстепенный - новая функциональность, но API изменяется обратно совместимым образом, а z - patch - увеличивается при исправлении ошибки обратно совместимым способом.

Это инструмент NPM для проверки.

Управление версиями JavaScript

NPM поощряет разработчиков JavaScript придерживаться методологии Semver. Это определенно следует учитывать при создании собственного рабочего процесса git.

Обновление внешних библиотек не должно быть частью вашего рабочего процесса Git

Если при работе с NPM вы не измените конфигурацию по умолчанию, установка новых пакетов приведет к их установке с помощью carat: ^. В вашем package.json вы увидите что-то вроде этого:

“dependencies”: { 
   “my_dep”: “^1.0.0”,
}

Если вы не хотите иметь карат и хотите использовать фиксированную версию, вы можете установить ее следующим образом:

npm install foobar --save --save-exact

Или, лучше, вы можете определить его в своем .npmrc файле конфигурации, например:

npm config set save=true
npm config set save-exact=true

Вышеизложенное взято из статьи Лучшие практики разработки на Node.js от Heroku. Но почему это рекомендуется?

Чтобы понять это, я настоятельно рекомендую прочитать Закрепление зависимостей и блокировка файлов от Renovate. Подведем итог по основным моментам:

  • «Файл блокировки [package-lock.json] заблокирует точные зависимости и sub -зависимости, которые использует ваш проект, так что все, кто запускает npm install, будут устанавливать те же зависимости, что и человек, который обновлял последний раз файл блокировки. " Вы можете понять, почему не использовать ваш файл блокировки проблематично - что-то может сломаться в процессе производства из-за изменения некоторой зависимости, и будет очень сложно отследить проблему, потому что у вас будет другая версия этой зависимости от вашего местная среда.
  • Файл блокировки не предназначен для чтения человеком. В случае, если выпущена новая версия сторонней библиотеки, которую вы используете, и она находится в диапазоне разрешенных версий в файле package.json, package-lock.json будет следить за тем, чтобы все использовали только фиксированную версию, которая была определяется, когда он был обновлен в последний раз. Например, в вашем package.json есть это определение:
“dependencies”: { 
   “my_dep”: “^1.0.0”,
}

Теперь, если my_dep команда выпустит новую основную версию 2.0.0, она никогда не будет использоваться вашим приложением, если вы не обновите ее вручную.

Но если они выпускают второстепенную версию, 1.2.0, то она не будет использоваться вашим приложением ни в какой среде, потому что файл блокировки обеспечивает использование фиксированной версии - той, которая находилась в диапазоне, который в прошлый раз он был обновлен.

Однако, если вы обновите файл блокировки (запустив npm update, который обновляет файл блокировки в соответствии с правилом, определенным в файле package.json), 1.2.0 станет вашей фиксированной версией, которая определена в файле блокировки, и она будет трудно это отследить.

  • Обычная рекомендация - использовать файл блокировки независимо от того, закреплены ли зависимости или нет, и закреплять, даже если у вас есть файл блокировки.

Если вы решите закрепить зависимости, вам понадобится какой-то автоматический механизм для их обновления, чтобы исправления безопасности и другие полезные новые функции не удивляли вас все время и не мешали вашему плану продукта. Renovate - одно из решений для этого, и Dependabot - тоже хороший вариант. Я уверен, что ты найдешь больше. Я думаю, что это отличное решение, даже если вы не прикрепляете версии, потому что всегда есть новые версии, которые могут быть вне диапазона.

Резюме

  1. Любому инженеру важно знать различные рабочие процессы Git, понимать методологию semver и то, как использовать файлы блокировки.
  2. Разным командам нужны разные рабочие процессы. Это зависит от рынка и команды, и рабочий процесс должен максимально упростить жизнь инженерам, использующим его, позволяя им быстро выпускать стабильный код.
  3. Я думаю, что наиболее близкий к тому, с чем я хочу работать, описан в этой статье - Feature Branch Workflow.
  4. Приятно использовать semver и фиксированные версии вместе со службой, которая помогает обновлять сторонние библиотеки.
  5. Я большой поклонник шаблонов проектирования и любил читать различные шаблоны для работы с Git.