Хотя концепция семантического управления версиями широко известна и используется в индустрии программного обеспечения, ее выполнение может быстро превратиться в запутанный беспорядок. Номер версии объявляется в нескольких местах (package.json, переменные среды, теги версий, конфигурации CI и т. Д.). Запоминание об обновлении всех этих местоположений создает нагрузку для памяти разработчика, и зачастую необходимость не забывать обновлять номер версии вообще часто не помогает. После того, как эта проблема постоянно мешала нашей стратегии развертывания в контрактном клубе, мы решили, что пришло время разработать длительный процесс. Чтобы увидеть рабочий пример, перейдите на https://bitbucket.org/Scfast/pipelines-autoversion или https://github.com/scfast/autoversion.

Шаг 1. Сократите все ссылки на номера версий до одного места.

Прямо вперед - поищите в своей кодовой базе и инструментах CI ссылки на номер версии и убедитесь, что все они ссылаются на одно и только одно место. По традиции мы использовали поле версии по умолчанию в package.json. Чтобы ссылаться на это значение в любом файле javascript, используйте следующее объявление:

const currentVersion = require(‘./package.json’).version;

Умышленное использование «const», чтобы номер версии оставался неизменным во время выполнения.

Чтобы указать номер версии в bash, наша команда использовала инструмент командной строки jq (https://stedolan.github.io/jq/download/). Подробнее об этом ниже.

Шаг 2. Настройте автоматическую пометку Git во время процесса непрерывной интеграции.

Часть CI нашей команды использует Bitbucket Pipelines. Команды, используемые для захвата номера версии и автоматической пометки репозитория, инициировавшего сборку, следующие:

- declare -x VERSION=$(jq -r '.version' package.json)
- echo $VERSION
- git tag $VERSION
- git push origin --tags

Единственная магия здесь может быть первой командой. По сути, инструмент командной строки «jq» ищет в файле package.json поле с именем «версия». Затем jq возвращает значение «версии» (скажем, «1.2.3»). Флаг «-r» удаляет кавычки из возвращаемого значения (сейчас только 1.2.3). Значение сохраняется в переменной VERSION, которая создается как тег и передается в ветку, запустившую сборку. Вы можете пометить кавычками, но после того, как я лично с этим справился, я рекомендую не использовать теги с кавычками по причинам, объяснение которых здесь займет слишком много времени.

Шаг 3. Определите стратегию управления версиями, которая больше напоминает рабочий процесс вашей группы.

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

Для Contract Club мы решили автоматизировать номер патча при каждом объединенном пулреквесте в мастер. Незначительные и основные обновления более субъективны и изменяются вручную, когда это оправдывается прогрессом разработки. Это было успешным с нашим стилем разработки на основе магистрали.

Возвращаясь к конвейерам Bitbucket, сначала реализуйте стратегию рабочего процесса ветвления (см. Https://confluence.atlassian.com/bitbucket/branch-workflows-856697482.html). Во-вторых, создайте сценарий для обновления номера патча в package.json. Мы просто использовали задачу gulp под названием автоверсия, чтобы выполнить это:

const gulp = require('gulp');
const runSequence = require('run-sequence'); // Run tasks sequentially
const jsonModify = require('gulp-json-modify');
gulp.task('upversion', function () {
let ver = require('./package.json').version; //version defined in the package.json file
console.log('current version: ', ver)
let splitString = ver.split('.', 3)
let patchVersion = splitString[2].split('"',1)let patchNumber = Number(patchVersion[0])
patchNumber++
splitString[2] = String(patchNumber);
process.env.VERSION = splitString.join('.');
console.log(process.env.VERSION)
})
gulp.task('saveversion', function () {
return gulp.src(['./package.json'])
.pipe(jsonModify({
key: 'version',
value: process.env.VERSION
}))
.pipe(gulp.dest('./'))
})
gulp.task('autoversion', function () {
runSequence('upversion','saveversion');
})

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

pipelines:
  default:
    - step:
      script:
        # Regular CI process for feature branches
  branches:
    master:
      - step:
        script:
          # PACKAGE INSTALLATIONS
          - npm install
          - npm install -g gulp
          # AUTO VERSIONING
          - git config remote.origin.url https://<URL to repository here>
          - gulp autoversion
          - git init
          - git config user.name "<your username>"
          - git config user.email "<your email>"
          - git add package.json
          - git commit -m "[skip CI]"
          - git push
          - declare -x VERSION=$(jq -r '.version' package.json)
          - echo $VERSION
          - git tag $VERSION
          - git remote -v
          - git push origin --tags

Пара заметок:

  • В этом примере используется HTTPS. Предпочтительно использование SSH. При использовании HTTPS убедитесь, что у пользователя есть доступ на запись к мастеру.
  • Сообщение фиксации «[пропустить CI]» необходимо, чтобы избежать повторного запуска сборки. Без него запустится бесконечный каскад сборок.

Вывод:

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

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