Здоровый подход

Немного истории как мы сюда попали.

Мы все были там в какой-то момент времени. Версии приложений упрощаются до целых чисел и увеличиваются с каждым выпуском… или нет. Случайность и отсутствие правил не помогали при работе в более крупной организации, когда несколько команд могли работать над одной кодовой базой. К счастью, решить проблему довольно легко, когда людям действительно не все равно.

Еще в 2016 году, после того как я закончил создание новой архитектуры для Yell.com, я начал задаваться вопросом, как лучше всего сделать версию нашего приложения. Как отразить серьезность релиза всего одним числом. Идея попробовать SemVer 2.0 пришла от моего бывшего начальника Стива Уоркмана. Это был мгновенный бай-ин от команды, хотя никто не хотел управлять им вручную. Поэтому мы внедряем сценарии процесса сборки для автоматизации версий в соответствии с нашими потребностями и подталкиваем к исправлению репозиториев, чтобы избежать коллизий и ошибок. Наш новый подход хорошо работал в течение многих лет и помог нам разработать лучшую стратегию ветвления git, управление примечаниями к выпуску и надежные конвейеры развертывания.

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

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

Кстати, о стратегии ветвления SimGit Flow вы можете прочитать в моем посте здесь.

Что такое СемВер 2.0?

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

Рассмотрим формат версии X.Y.Z (Major.Minor.Patch). Исправления ошибок, не влияющие на API, увеличивают версию исправления, дополнения/изменения, совместимые с предыдущими версиями, увеличивают дополнительную версию, а изменения, несовместимые с предыдущими версиями, увеличивают основную версию.

Подробнее о семантическом версионировании читайте здесь:



Он был разработан с учетом API, но очень хорошо работает с внешними приложениями, особенно при работе с несколькими приложениями в монорепозитории и совместном использовании между ними набора функций (ядра). Стратегия ветвления SimGit Flow использует это управление версиями для именования ветвей; таким образом, это идеальное совпадение, если вы используете подход SemVer, поскольку вы можете доверять обратной совместимости, основываясь только на номере версии.

Как это работает?

Учитывая номер версии MAJOR.MINOR.PATCH, увеличьте:

  1. ОСНОВНАЯ версия, когда вы вносите несовместимые изменения.
    Это может включать в себя значительные изменения дизайна и вещи, которые каким-то образом «открывают новую эру», как я это называю. Например, за 4 года в Yell мы дошли только до версии 9.x.x.
  2. ВНЕШНЯЯ версия, когда вы добавляете обратную функциональность.
    К ним относятся типичные выпуски с новыми функциями и функциями, добавленными на сайт. Иногда эти обновления могут быть несовместимы с предыдущими версиями для данного приложения из вашего монорепозитория, но это нормально, если ядро ​​(общие компоненты) совместимо. В некоторых случаях мы можем использовать небольшие неровности для исправления ошибок, но это зависит от ситуации, поскольку мы не всегда хотели использовать подход исправления.
  3. PATCH версия, когда вы исправляете ошибки с обратной совместимостью.
    Когда новая сборка готовится как x.x.0, мы проводим тестирование, находим ошибки, исправляем и снова развертываем. Каждая итерация и исправления увеличивают версию патча. Новый выпуск почти всегда требует небольших исправлений после проверки QA. Patch Bump также будет использоваться почти всегда, когда нам нужно сделать исправление для работающего кода.

Как мы используем SemVer в наших приложениях?

  • Мы храним версию в package.jsonфайле. Это логичный выбор для такой информации, и процесс сборки может легко получить к ней доступ.
  • Мы используем номер версии для очистка кеша. Все наши файлы сборки и ресурсы имеют суффиксы с версией приложения, поэтому нам не нужно беспокоиться о проблемах с кэшированием всякий раз, когда развертывается новый код. Кроме того, он удобочитаем для быстрого определения источника проблем и развернутых версий.
  • Мы использовали MAJOR.MINOR для названия веток релиза. Это помогает быстро находить код и развертывать исправления для определенных версий, не затрагивая другие ветки.
  • Все сторонние средства аналитики и повышения производительности получают номер версии в наборе данных, чтобы мы могли быстро выявлять аномалии и проблемы и привязывать их к конкретной версии.
  • После создания каждой сборки мы архивируем все файлы в один пакет и используем версию приложения в качестве имени файла. Просто облегчает (опять же) поиск позже.
  • Мы стремимся создать среды выпуска на основе версий и уничтожить их, как только код будет запущен. Это позволит нам иметь более одного выпуска в данный момент времени.
  • … и более

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

В основной или дополнительной сборке скрипт создает новую ветку релиза, чтобы объединить туда весь код. После того, как это сделано, любое обновление для этого конкретного выпуска является «сборкой исправления».

При сборке патча нам нужно указать номер версии (major.minor), и скрипт выполнит извлечение в этой конкретной ветке, поднимет версию патча, соберет пакет и развернет.

Как только все будет протестировано, и мы будем довольны, мы можем начать работу. Все это является частью наших автоматизированных конвейеров, которые объединяют стратегию ветвления SimGit Flow, о которой я упоминал ранее, управление версиями SemVer и поток примечаний к выпуску (о них я расскажу в следующем посте в ближайшее время).

Пример скрипта для работы с обновлениями версий

Это пример нашего процесса сборки и того, как мы с ним справляемся.

Несколько вещей, которые вам, вероятно, понадобятся:

/**
 * Install semver NPM package to deal with versioning
 */
npm install -D semver
npm install -D shelljs // optional

И скрипт, который поможет вам справиться с обновлениями:

/**
 * Check what build you are preparing as you will need to pass
 * the name to semver script to update to the new version.
 */
const ALLOWED = {
    patch: true,
    minor: true,
    major: true
};
if (!ALLOWED[process.argv.slice(2)[0]]) {
    console.log('\x1b[31m* Wrong version type!\x1b[0m');
    shell.exit();
} else {
    buildType = process.argv.slice(2)[0];
}
/**
 * Run version update.
 * Read package.json, update version based on buildType, save back.
 */
let rawdata = fs.readFileSync('package.json');
let packageJson = JSON.parse(rawdata);
console.log('* Current version is', packageJson.version);
packageJson.version = semver.inc(packageJson.version, buildType);
console.log('* New version is', packageJson.version);

// save package json
let data = JSON.stringify(packageJson);
fs.writeFileSync('package.json', data);
/**
 * Make it pretty again ;)
 */
shell.exec('npx prettier --write package.json');

Хорошо то, что пакет semver npm позаботится обо всей логике, необходимой для правильного обновления имени вашей версии. Все, что вам нужно сделать, это прочитать текущую версию, предоставить ее semver и сказать, что вы хотите с ней сделать.

Мы используем shelljs для выполнения функций оболочки из наших сценариев npm. Вы увидите это в приведенном выше коде как shell.exec().

Последние несколько слов…

Это не высшая математика, но я часто видел хаос в командах разработчиков и версий приложений, которые следовали свободному или случайному подходу без формального соглашения. Что бы вы ни решили сделать, убедитесь, что это записано, объяснено и реализовано всеми разработчиками. Лучший процесс потерпит неудачу, если за ним не будут следовать команды.

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

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