Рубрики
Uncategorized

Автоматизация релизов Maven с Circleci

Maven, вероятно, единственный все в один инструмент сборки, который я когда-либо ценил. Я, вероятно, приду к … с меткой DevOps, Bash, Showdev.

Maven, вероятно, единственный универсальный инструмент сборки, который я когда-либо действительно ценится . Я, вероятно, придет к сделать в конце концов и цементный статус статус старого до-до того времени * Nix Crola, но у меня еще не было причины действительно копаться Так что Maven это. И я вернулся в магазин в основном-Java, поэтому давайте повеселимся!

Цель этой недели: автоматизация выбросов из нашего экземпляра Circleci. Звучит достаточно просто, верно? Поднять версию, отрежьте тег, опубликуйте. Как трудно это может быть?

Ну, во-первых, мы используем Git-flow или, по крайней мере, мы сохраняем Мастер Для выпусков и отработка отдельных проверить ветвь. Бюджетный поток Git, если вы будете. Это одно осложнение, поскольку релиз должен быть помечен на Мастер Но проверить Также необходимо обновить, поэтому два не расходятся.

Если вы знакомы с Maven, вы, возможно, уже угадали второе осложнение. Это слоется. Maven не работает в приятных, простых СЕМВЕР : Maven принимает несколько различных схем версий и имеет специальную Снимок Квалификатор для не высвобождения. Если вы работаете в направлении Release 1.0, ваш номер версии 1,0 — снимок. После того, как вы сократите выпуск, вы возобновите развитие с 1.1-Snapshot (или 2.0-Snapshot, если он действительно нуждается в переделке уже). И так далее. Это не имел в виду быть автоматическим, потому что релизы являются большое дело В мире Maven, и вы должны иметь план для того, что вы собираетесь делать дальше, а не реагируете на то, не закреплены ли вы ошибки, представленные функции или сломали совместимость. И, честно говоря, есть некоторые убедительные аргументы для этого таким образом.

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

Рабочий процесс

Мы используем круг V2 и его функцию рабочего процесса для организации сборки. Каждая ветвь построен: проверить и Мастер Развернуты для артефактирования, а Выпуск Запускает свою собственную работу, которая последняя — это линхпин всей структуры.

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: /^(master|verify)$/
      - release:
          requires:
            - build
          filters:
            branches:
              only: /^release$/

Просто построить

Я буду честен, я скопировал и вставил большую часть этого определения работы прямо из документов:

steps:
  - checkout
  - restore_cache:
      keys:
      - v1-dependencies-{{ checksum "pom.xml" }}
      # fallback to using the latest cache if no exact match is found
      - v1-dependencies-
  - run: mvn clean install
  - save_cache:
      paths:
        - ~/.m2
      key: v1-dependencies-{{ checksum "pom.xml" }}
  - persist_to_workspace:
      <<: *source

Мы кэшируем наши зависимости, потому что это то, как это делает; MVN чистая установка Вероятно, наполнен (нам, вероятно, не нужно беспокоиться с установкой зависимости от локального кэша Maven), но он создает и запускает наши тесты и генерирует артефакт. Единственная действительно интересная часть вот в том, что мы сохраняем важные файлы на рабочую область, чтобы мы могли восстановить его позже — * Источник Относится к другому блоку YAML с root Строка и список путь .

А также Развертывать

steps:
  - attach_workspace:
      at: .
  - run:
      name: Deploy to Artifactory
      command: mvn deploy

Вот где мы используем это рабочее пространство. Всякий раз, когда эта работа работает, она будет присоединиться к структуре файла, которую мы сохранили с работы по сборке. MVN Развертывание Все еще управляет всеми промежуточными этапами жизненного цикла, потому что это то, как Maven Rolls, но нам не нужно снова проверить код.

У нас есть наши помпы, настроенные с Artifactory-Maven-плагин Так что все, что мы должны сделать, чтобы опубликовать, это выпуск MVN Развертывание . Это делает это просто, по крайней мере; Есть артефактория CLI, если вы предпочитаете, но всю сделку Maven управляется всем, насколько я понимаю, мы должны позволить этому.

Есть только одна кусочка, хотя: как мы на самом деле выпустим новый Версия артефакта и начнутся на начало следующего?

Триггер выпуска

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

Это будет сложно. Вот …| Выпуск Построить шаги в полном объеме:

steps:
  - checkout
  - run:
      name: Cut new release
      command: |
        # assemble current and new version numbers
        OLD_VERSION=$(mvn -s .circleci/settings.xml -q \
          -Dexec.executable="echo" -Dexec.args='${project.version}' \
          --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
        NEW_VERSION="${OLD_VERSION/-SNAPSHOT/}"
        echo "Releasing $OLD_VERSION as $NEW_VERSION"

        # ensure dependencies use release versions
        mvn -s .circleci/settings.xml versions:use-releases

        # write release version to POM
        mvn -s .circleci/settings.xml versions:set -DnewVersion="$NEW_VERSION"

        # setup git
        git config user.name "Release Script"
        git config user.email "builds@understoryweather.com"

        # commit and tag
        git add pom.xml
        git commit -m "release: $NEW_VERSION"
        git tag "$NEW_VERSION"

        # land on master and publish
        git checkout master
        git merge --no-edit release
        git push origin master --tags

        # increment minor version number
        MAJ_VERSION=$(echo "$NEW_VERSION" | cut -d '.' -f 1)
        MIN_VERSION=$(echo "$NEW_VERSION" | cut -d '.' -f 2)
        NEW_MINOR=$(($MIN_VERSION + 1))
        DEV_VERSION="$MAJ_VERSION.$NEW_MINOR-SNAPSHOT"

        # ready development branch
        git checkout verify
        git merge --no-edit release
        mvn -s .circleci/settings.xml versions:set -DnewVersion="$DEV_VERSION"
        git add pom.xml
        git commit -m "ready for development: $DEV_VERSION"
        git push origin verify

        # clean up release branch
        git push origin :release

Это не грязный , но это … много скрипта Bash. Но, как и любая достаточно сложная задача базы данных, включает в себя запись SQL, любая достаточно сложная задача OPS включает в себя Bash. Давайте сломаемся:

Получение номеров версий

# assemble current and new version numbers
OLD_VERSION=$(mvn -s .circleci/settings.xml -q \
  -Dexec.executable="echo" -Dexec.args='${project.version}' \
  --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
NEW_VERSION="${OLD_VERSION/-SNAPSHOT/}"
echo "Releasing $OLD_VERSION as $NEW_VERSION"

Обратите внимание на -scircleci/settings.xml : Поскольку кружок просто спиннирует основное изображение OpenJDK, у нас есть settings.xml проверено в контроль источника. Учетные данные интерполированы через переменные среды, но это все еще не большой ; В какой-то момент я захочу вернуться и создать пользовательский документ Docker, чтобы централизовать нашу конфигурацию.

Maven хранит номера версий в POM. Мы могли бы вытащить их с XPath, но поскольку это Maven, для этого есть плагин. Old_Version это текущее значение; Так как мы всегда выпускаем из проверить Филиал, это гарантированно является версией снимков, и нам нужно раздеть эту квалификацию, чтобы получить New_version для выпуска.

Обновлять версии

# ensure dependencies use release versions
mvn -s .circleci/settings.xml versions:use-releases

# write release version to POM
mvn -s .circleci/settings.xml versions:set -DnewVersion="$NEW_VERSION"

У нас нет тонны библиотек Java, но достаточно, чтобы управление выпуском — это (очевидно). Первое утверждение здесь гарантирует, что когда мы выпустим, мы не в зависимости от версии снимки другого из наших библиотек. Второе на самом деле на самом деле устанавливает поле версии в POM к версии выпуска, которую мы создали только сейчас.

Вы можете спросить: почему я не просто псевдоним МВН к mvn -s .circleci/settings.xml ? И ответ: я сделал, и потратил пол дня, пытаясь выяснить, почему это не сработало. Я не знаю, является ли это конкретное изображение или круг в целом или что, но псевдоним просто игнорируются.

Выпускать!

# setup git
git config user.name "Release Script"
git config user.email "builds@understoryweather.com"

# commit and tag
git add pom.xml
git commit -m "release: $NEW_VERSION"
git tag "$NEW_VERSION"

# land on master and publish
git checkout master
git merge --no-edit release
git push origin master --tags

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

Далее мы совершаем обновленный POM и создать тег. Когда мы объединяемся (с --no - редактировать поскольку скрипт не может изменить сообщение COMMING), релиз-коммит и тег приземляется на Мастер ветвь. Тогда это просто вопрос толкания в начало происхождения.

Следующий…

Мы выпустили, но мы не совсем сделаны. Если мы оставили это здесь, следующий выпуск из проверить Филиал вступит в конфликты слияния с Мастер Имеет обновленную версию в POM. Чтобы предотвратить это, мы должны объединиться вернуться в проверять . Предпочтительно с квалификатором версии снимка, потому что Maven.

# increment minor version number
MAJ_VERSION=$(echo "$NEW_VERSION" | cut -d '.' -f 1)
MIN_VERSION=$(echo "$NEW_VERSION" | cut -d '.' -f 2)
NEW_MINOR=$(($MIN_VERSION + 1))
DEV_VERSION="$MAJ_VERSION.$NEW_MINOR-SNAPSHOT"

Я включал нас в двух частях номеров версий строго из удобства. Поскольку Maven ожидает, что вы узнаете, что вы работаете, собираясь от 1,0 до 1,1 гораздо более реалистично, чем пытаться выйти, вы смотрите на 1,0,1 или 1.1,0 следующий. Мы всегда можем обновить версию себя, если решать следующий релиз, на самом деле должен быть 2.0, но я пытаюсь минимизировать участие человека здесь.

# ready development branch
git checkout verify
git merge --no-edit release
mvn -s .circleci/settings.xml versions:set -DnewVersion="$DEV_VERSION"
git add pom.xml
git commit -m "ready for development: $DEV_VERSION"
git push origin verify

Слияние Выпуск в проверить Сохраняет нас от любых потенциальных конфликтов слияния вниз по линии, поскольку в том же выпуске Commite теперь существует как на Мастер и в проверить Отказ Сценарий затем добавляет второй фиксацию на проверить С новой версией Snapshot и отправляет все это вплоть до начала.

# clean up release branch
git push origin :release

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

Отключение его

git checkout -b release
git push origin release

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

Оригинал: «https://dev.to/dmfay/automating-maven-releases-with-circleci-1gmc»