Я обычно работаю с серверной Java и почти в любое приложение (Tomcat/Spring/Play...) требуется добавить end-point, который при HTTP запросе сообщит номер и время сборки приложения. Я перепробовал разные способы и нашел тот, который меня устраивает во всем. Процесс интеграции в любое Java приложение занимает 5-10 минут.
Для начала нужно зарегистрироваться на Backendless и создать там приложение (можно использовать любой другой сервис, который умеет по http запросу отдавать число, увеличивая его каждый раз на 1). Получив APP_ID приложения нужно также получить API_KEY на этой странице.
После этого вы сможете использовать возможность получать целое число, которое будет увеличиваться на 1 после каждого запроса.
Для того, чтобы это число попадало в программу, нужно воспользоваться моей OpenSource библиотекой kolobok. Указываем зависимость на библиотеку в pom.xml или build.gradle.
<dependency>
<groupId>com.github.ukman</groupId>
<artifactId>kolobok</artifactId>
<version>0.1.5</version>
<scope>compile</scope>
</dependency>
compileOnly 'com.github.ukman:kolobok:0.1.5'
Добавляем аннотацию для поля в каком-либо классе (не забывая прописать правильный APP_ID и API_KEY внутри параметра url).
import org.kolobok.annotation.*;
public class Main {
@BuildNumber(url = "https://api.backendless.com/${APP_ID}/${API_KEY}/counters/build/increment/get", method = "PUT")
public static long bn;
@CompileTime
public static long ct;
public static void main(String args[]) {
System.out.println("Build number = " + bn + " compilation time " + new Date(ct));
}
}
Теперь после каждой перекомпиляции класса Main у вас в поле bn будет новое число из последовательности возрастающих чисел, а в поле ct- время компиляции. То есть на вход компилятору уйдет что-то вроде.
public static long bn = 1; // 2..3..4..5..
public static long ct = 1580107708793; // System.currentTimeMillis()
После инкрементальной сборки, файл Main.java может не перекомпилироваться и значения останутся прежними, но обычно делают полную очистку всех скомпилированных файлов перед полной сборкой, а значит номер сборки будет обновлен.
Теперь можно использовать эти переменные для показа номера и времени сборки пользователю.
Elufimov
Рассчитывать текущую версию на базе текущего коммита в гите не подходит потому что не используется внешний веб сервис?
ukman Автор
Статья не про номер версию, статья про номер сборки. Это немного разные вещи. На базе одного комита вы можете сделать много билдов с одинаковым номером версии и разным номером сборки.
Elufimov
Зачем отдельно выделять номер сборки, особенно таким, мягко говоря, нетривиальным решением с привлечением стороннего сервиса?
ukman Автор
У нас случается проблема иногда- билд почему-то собирается неправильно. Например ошиблись при обновлении скриптов в bamboo. Вышел неверный билд. Его раскидали клиентам. Обнаружили проблему. Починили скрипты, заново собрали билд. Формально версия не поменялась. Но сборки совершенно разные. С номером сборки у вас есть контроль над тем, какая именно сборка стоит у клиентов. Чтобы не использовать сторонний сервис, можно ограничиться временем сборки, но ее неудобно передавать голосом по телефону: "проверьте что у вас время сборки от 27 января, 10 часов, 42 минуты", удобнее: "проверьте что у вас номер сборки 10542".
Elufimov
Незнаю как bamboo, но teamcity имеет в переменных которые передаются в билд в том числе и номер сборки, который можно совместить с информацией полученной из гита, и получить уникальную версию. Мне кажется в bamboo тоже должна быть возможность получить номер сборки.
ukman Автор
Вы рассуждаете как человек, который работает в рамках сложившейся инфраструктуры, давно и долго работающий с одним проектом. Мы например часто по работе создаем прототипы. Надо за пару дней запилить сервис, поставить, собрать обратную связь, убить или продолжить снова. Тут нужны легкие простые решения. В случае с bamboo/teamcity — надо привлекать DevOps команду, которая настроит план- тяжело.
Пусть расцветают тысячи цветов. Мира вам.
Elufimov
Я старонник мнения что нужно всегда стараться вникать в те проблемы с которыми сталкиваешься, особенно если сталкиваешься с ними постоянно. Практики DevOps это не магия, и не что-то запредельно сложное. Надеюсь в следующий раз когда будете решать похожую задачу, то воспользуетесь тем что предлагает ваша система сборки а не будете делать свой велосипед на пустом месте.
И вам того же.
berez
Когда номер сборки дорастет до шестизначных чисел, разницы для пользователя никакой уже не будет. Ему что 202001271101, что 104327 фиг прочитаешь. Все равно придется только последние три -четыре цифры диктовать.
ukman Автор
Номер билдов растут очень медленно, максимум 4-5 билдов в день на проекте. 1000 билдов в год. Через 10 лет по достижении 9999 можно начать сначала.
berez
По-хорошему, такого просто не должно быть. Если у вас система сборки отдельная от исходников, да еще и правится на билд-сервере вручную — это очень, очень нехорошо, уж поверьте мне. Со временем в эту билд-систему заползает множество подпорочек и грабелек, и если потом эту систему перенести на другую машину, то все эти подпорочки и грабельки повылезают.
В идеале должен работать такой сценарий:
— Готовим новую машину для билда. По списку ставим на нее необходимый софт (компилятор, git/svn, maven и т.п.).
— Отводим дисковое пространство под сборку. Настраиваем переменные окружения.
— Вычекиваем из репозитории нужную версию исходников с системой сборки.
— Запускаем сборку.
При правильном подходе все срабатывает искаропки: система сборки находит все исходники, подтягивает откуда надо зависимости, все собирает и пакует готовый билд. При неправильном вас ждет масса увлекательных расследований «почему сейчас-то не собирается?».
ukman Автор
Да, согласен, вы все правильно говорите. В идеальном мире все так.
В реальном мире программеры часто даже не знают кто занимается сборками, особенно в распределенных командах и настройка билдов порой занимает много месяцев, особенно для "второстепенных" проектов. И мы можем сколько угодно говорить что все надо делать как нужно, а как не нужно- делать не нужно…
Вот от такого несовершенства и приходится иметь разные инструменты для разных жизненных ситуаций.
berez
Вы серьезно? Много месяцев? Такого я не видел даже в крупных конторах на древних легаси-проектах на С++ — хотя там полная сборка могла идти пару суток. Рано или поздно ставили какой-нибудь Jenkins и разработчики сами должны были добиваться, чтобы их модули компилировались без граблей.