Строка и нумерация версий для проектов Java (ant, cvs, hudson)



Answers

Ваш файл build.xml

...
<property name="version" value="1.0"/>
...
<target name="jar" depends="compile">
    <buildnumber file="build.num"/>
    <manifest file="MANIFEST.MF">
        ...
        <attribute name="Main-Class" value="MyClass"/>
        <attribute name="Implementation-Version" value="${version}.${build.number}"/>
        ...
    </manifest>
</target>
...

Ваш Java-код

String ver = MyClass.class.getPackage().getImplementationVersion();
Question

Каковы текущие лучшие практики для систематической нумерации сборки и управления номерами версий в проектах Java? В частности:

  • Как систематически управлять номерами сборки в распределенной среде разработки

  • Как поддерживать номера версий в источнике / доступны для приложения времени выполнения

  • Как правильно интегрировать исходный репозиторий

  • Как более автоматически управлять номерами версий и тегами репозитория

  • Как интегрироваться с инфраструктурой непрерывной сборки

Существует множество инструментов, и ant (система сборки, которую мы используем) имеет задачу, которая будет поддерживать номер сборки, но неясно, как управлять этим с помощью нескольких одновременных разработчиков, использующих CVS, svn или аналогичные ,

[РЕДАКТИРОВАТЬ]

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

  • Если вы используете SVN, для езды выдается версия определенного заказа. Строка нумерации может использовать это, чтобы создать уникальный номер сборки, который идентифицирует конкретный checkout / revision. [CVS, который мы используем по причинам, связанным с наследством, не дает такого уровня понимания ... ручное вмешательство с тегами поможет вам в этом частично.]

  • Если вы используете maven как свою систему сборки, есть поддержка для выпуска номера версии из SCM, а также модуль выпуска для автоматического выпуска релизов. [Мы не можем использовать maven по разным причинам, но это помогает тем, кто может. [Благодаря marcelo-morales ]]

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

  • Ant и maven (и hudson и круиз-контроль) обеспечивают легкое средство для получения чисел сборки в файле .properties или в файле .txt / .html. Является ли это «безопасным», чтобы он не был подделан намеренно или случайно? Лучше ли компилировать его в класс «версия» во время сборки?

  • Утверждение: Нумерация сборки должна быть определена / введена в систему непрерывной интеграции, например, hudson . [Спасибо marcelo-morales ] Мы приняли это предложение, но он взломал вопрос о выпуске релиза: как происходит релиз? Есть ли множественные buildnumbers в выпуске? Есть ли значимые отношения между buildnumbers из разных выпусков?

  • Вопрос: Какова цель построения номера сборки? Используется ли он для QA? Как? Используется ли он прежде всего разработчиками для устранения неоднозначности между несколькими сборками во время разработки или более для QA, чтобы определить, что построил конечный пользователь? Если целью является воспроизводимость, теоретически это то, что должен предоставить номер версии выпуска - почему? (пожалуйста, ответьте на это как часть ваших ответов ниже, это поможет осветить выбранные вами варианты / предлагаемые ...)

  • Вопрос: Есть ли место для номеров сборки в ручных сборках? Это настолько проблематично, что КАЖДЫЙ должен использовать решение CI?

  • Вопрос: Следует ли проверять номера сборки в SCM? Если цель надежно и однозначно идентифицирует конкретную сборку, как справиться с множеством непрерывных или ручных систем сборки, которые могут выходить из строя / перезапускать / и т. Д. ...

  • Вопрос: Должен ли номер сборки быть коротким и сладким (т. Е. Монотонно увеличивать целое число), так что его легко вставлять в имена файлов для архивирования, легко ссылаться на связь и т. Д. ... или он должен быть длинным и полным имен пользователей, datestamps, имена машин и т. д.?

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

Мне бы очень хотелось, чтобы это было полным ответом, по крайней мере, для конкретного примера нашей установки cvs / ant / hudson, поэтому кто-то мог построить полную стратегию, основанную на этом вопросе. Я буду отмечать как «Ответ» любого, кто может дать описание супа-орехов для этого конкретного случая (включая схему тегов cvs, соответствующие элементы конфигурации CI и процедуру освобождения, которая сводит номер сборки в выпуск, так что она программно доступный.) Если вы хотите спросить / ответить на другую конкретную конфигурацию (например, svn / maven / круиз-контроль), я свяжусь с вопросом здесь. --JA

[РЕДАКТИРОВАТЬ 23 окт. 09] Я принял ответ на верхний голос, потому что я думаю, что это разумное решение, в то время как некоторые другие ответы также включают хорошие идеи. Если кто-то хочет взломать синтез некоторых из них с marty-lamb , я подумаю о принятии другого. Единственная проблема, с которой я сталкиваюсь с marty-lamb, заключается в том, что она не создает надежного сериализованного номера сборки - это зависит от местных часов в системе строителя, чтобы обеспечить однозначные строковые номера, что не очень удобно.

[Редактировать Jul 10]

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

public final class AppVersion
{
   // SVN should fill this out with the latest tag when it's checked out.

   private static final String APP_SVNURL_RAW = 
     "$HeadURL: svn+ssh://user@host/svnroot/app/trunk/src/AppVersion.java $";
   private static final String APP_SVN_REVISION_RAW = "$Revision: 325 $";  

   private static final Pattern SVNBRANCH_PAT = 
     Pattern.compile("(branches|trunk|releases)\\/([\\w\\.\\-]+)\\/.*");
   private static final String APP_SVNTAIL = 
     APP_SVNURL_RAW.replaceFirst(".*\\/svnroot\\/app\\/", "");

  private static final String APP_BRANCHTAG;
  private static final String APP_BRANCHTAG_NAME;
  private static final String APP_SVNREVISION = 
    APP_SVN_REVISION_RAW.replaceAll("\\$Revision:\\s*","").replaceAll("\\s*\\$", "");


  static {
    Matcher m = SVNBRANCH_PAT.matcher(APP_SVNTAIL);
    if (!m.matches()) {
      APP_BRANCHTAG = "[Broken SVN Info]";
      APP_BRANCHTAG_NAME = "[Broken SVN Info]";
    } else {
      APP_BRANCHTAG = m.group(1);
      if (APP_BRANCHTAG.equals("trunk")) {
        // this isn't necessary in this SO example, but it 
        // is since we don't call it trunk in the real case
        APP_BRANCHTAG_NAME = "trunk";
      } else {
        APP_BRANCHTAG_NAME = m.group(2);
      }
    }
  }

  public static String tagOrBranchName()
  { return APP_BRANCHTAG_NAME; }

  /** Answers a formatter String descriptor for the app version.
   * @return version string */
  public static String longStringVersion()
  { return "app "+tagOrBranchName()+" ("+
    tagOrBranchName()+", svn revision="+svnRevision()+")"; }

  public static String shortStringVersion()
  { return tagOrBranchName(); }

  public static String svnVersion()
  { return APP_SVNURL_RAW; }

  public static String svnRevision()
  { return APP_SVNREVISION; }

  public static String svnBranchId()
  { return APP_BRANCHTAG + "/" + APP_BRANCHTAG_NAME; } 

  public static final String banner()
  {
    StringBuilder sb = new StringBuilder();
    sb.append("\n----------------------------------------------------------------");
    sb.append("\nApplication -- ");
    sb.append(longStringVersion());
    sb.append("\n----------------------------------------------------------------\n");
    return sb.toString();
  }
}

Оставьте комментарии, если это заслуживает обсуждения в вики.




Вы также можете взглянуть на плагин BuildNumber Maven и задачу Ant в одной банке, найденной по адресу http://code.google.com/p/codebistro/wiki/BuildNumber . Я попытался сделать это простым и понятным. Это очень маленький файл jar, который зависит только от установленной командной строки Subversion.




Программного обеспечения:

  • SVN
  • Муравей
  • Хадсон, для непрерывной интеграции
  • svntask, задача Ant для поиска версии SVN: http://code.google.com/p/svntask/

Хадсон имеет три сборки / задания: непрерывный, ночной и выпуск.

Для сборки Continuous / Nightly: номер сборки - это версия SVN, найденная с использованием svntask.

Для сборки / задания выпуска: номер сборки - номер версии, прочитанный Ant, из файла свойств. Файл свойств также может быть распространен вместе с релизом для отображения номера сборки во время выполнения.

Скрипт сборки Ant помещает номер сборки в файл манифеста файлов jar / war, созданных во время сборки. Применяется ко всем сборкам.

Действие пост-сборки для версий Release, легко выполняется с помощью подключаемого модуля Hudson: тега SVN с номером сборки.

Выгоды:

  • Для dev-версии jar / war разработчик может найти версию SVN из jar / war и найти соответствующий код в SVN
  • Для выпуска версия SVN является версией, соответствующей тегу SVN, в котором есть номер выпуска.

Надеюсь это поможет.




Вот мои 2 цента:

  • Мой скрипт сборки создает номер сборки (с меткой времени!) Каждый раз, когда я создаю приложение. Это создает слишком много чисел, но их слишком мало. Если у меня есть изменение в коде, номер сборки изменится хотя бы один раз.

  • Я использую номер сборки с каждой версией (хотя и не между ними). Когда я обновляю проект и получаю новый номер сборки (потому что кто-то еще сделал выпуск), я перезаписываю свою локальную версию и начинаю все заново. Это может привести к более низкому числу сборки, поэтому я включил метку времени.

  • Когда происходит релиз, номер сборки фиксируется как последний элемент в одном коммите с сообщением «сборка 1547». После этого, когда это официальный релиз, все дерево помечено. Таким образом, файл сборки всегда имеет все теги, и существует простое сопоставление 1: 1 между тегами и номерами сборки.

[EDIT] Я развертываю version.html с моими проектами, а затем, я могу использовать скребок, чтобы просто собрать точную карту, что установлено где. Если вы используете Tomcat или подобное, поместите номер сборки и временную метку в элемент description web.xml . Помните: никогда не запоминайте что-либо, когда вы можете заставить компьютер сделать это за вас.




Related