Иногда, когда я покупаю еду, я проверяю этикетку, чтобы увидеть, насколько это вредно для здоровья, чтобы напомнить себе, что нужно есть лучше.  Я, вероятно, должен делать это чаще, но это другая история. 
С программным обеспечением я беру более строгий подход. Мне нравится точно знать, какая версия того, что я использую, и, если это относится к сборке, полученной из проекта, над которым я работаю, мне бы хотелось узнать еще больше:
- ветвь, из которой это произошло
 - любые изменения кода или конфигурации
 - время сборки
 - человек, который сделал сборку
 - ревизия коммита соответствует
 
Преимущества этого очевидны, но заслуживают повторения.
- Пока вы находитесь в разработке, если у вас есть несколько развертываний и вы видите что-то необычное, вы сразу захотите сравнить их.
 
Например, скажем, у вас есть:
- сборка № 349 на коробке 1
 - сборка # 352 на блоке 2 (которая включает изменения разработки из функциональной ветви Y)
 
Вы замечаете какое-то странное поведение для сообщения об ошибке в блоке 2, но не в блоке 1. Вы можете сразу проверить, какой блок имеет какую версию, затем проверить изменения и затем попытаться рационализировать разницу.
- Вы можете быть уверены, что ваша последняя регистрация кода развернута
 - Вся эта информация о сборке должна быть в официальных примечаниях к выпуску, поэтому, если вы можете автоматизировать ее как часть процесса разработки, вы избавили себя от необходимости автоматизировать ее как часть своего выпуска.
 - В корпоративных архитектурах, где у вас есть несколько компонентов, разработанных различными группами, интегрирующимися друг с другом, все компоненты должны облегчать получение этой информации. Это помогает управлять стеком и позволяет каждому немедленно проверить, были ли развернуты новые версии каких-либо компонентов, или откатиться до стабильных версий, если возникнут проблемы с какими-либо обновлениями компонентов.
 
Так что покончим с мнениями, а теперь с некоторыми примерами. В проекте, над которым я сейчас работаю, используется архитектура на основе Grails и Bamboo Atlassian для сборки и развертывания. Я хотел, чтобы эта информация, которую я описал, была в каждой сборке — и да, она включает каждую сборку разработки. Сейчас я опишу шаги.
Шаг 1
Напишите обработчик событий, который будет выполняться при создании войны. Это должно прочитать кучу системных свойств (которые вы установите в бамбуке) и поместить их в ваш application.properties вашего war-файла. Пример:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
 | 
eventCreateWarStart = { warName, stagingDir ->    def buildNumber = System.getProperty( "build.number", "CUSTOM" )     def buildTimeStamp= System.getProperty("build.timeStamp", "")     def buildUserName= System.getProperty("build.userName", "")    def repositoryRepositoryUrl= System.getProperty("repository.repositoryUrl",  "")    def repositoryRevisionNumber= System.getProperty("repository.revision.number", "")    def repositoryBranch= System.getProperty("repository.branch", "")    ant.propertyfile(file: "${stagingDir}/WEB-INF/classes/application.properties") {        entry(key:"build.number", value:buildNumber)         entry(key:"build.timestamp", value: buildTimeStamp)        entry(key:"build.userName", value: buildUserName)        entry(key:"repository.revision.number", value: repositoryRevisionNumber)        entry(key:"repository.branch", value: repositoryBranch)     }} | 
Шаг 2
Обновите свою бамбуковую сборку, чтобы установить эти системные свойства во время войны. Чтобы сделать это, обновите задачу build war примерно так:
| 
 1 
2 
3 
4 
5 
 | 
war -Dbuild.number=${bamboo.buildNumber}     -Drepository.branch=${bamboo.repository.git.branch}     -Dbuild.userName=${bamboo.ManualBuildTriggerReason.userName}     -Dbuild.timeStamp=${bamboo.buildTimeStamp}     -Drepository.revision.number=${bamboo.repository.revision.number} | 
Это будет означать, что когда Bamboo строит вашу войну, все вышеупомянутые свойства будут добавлены в ваш файл application.properties.
Шаг 3
Теперь все, что вам нужно сделать, это облегчить GSP Grails чтение этих свойств и их отображение. Это означает, что при развертывании все, что нужно будет сделать, это нажать на специальный URL-адрес, и тогда они получат всю информацию о сборке для развернутой WAR.
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
...... Some CSS and JavaScript  <h1>Environment: ${grails.util.Environment.current.name}</h1><hr>  <h4>Build Info:</h4><table class="altrowstable" id="alternatecolor"><thead><tr><td>Name</td><td>Value</td></tr></thead><tbody><tr><td>UserName</td><td>#${g.meta([name: 'build.userName'])}</td></tr><tr><td>Built by</td><td> #${g.meta([name: 'build.number'])}</td></tr><tr><td>Date</td><td>#${g.meta([name: 'build.date'])}</td></tr><tr><td>Branch</td><td>#${g.meta([name: 'repository.branch'])}</td></tr><tr><td>Revision number</td><td>#${g.meta([name: 'repository.revision.number'])}</td></tr></tbody></table> | 
И в духе пищевых аналогий … Вот что я сделал ранее и как это выглядит
 
  Итак, программное обеспечение воспринимается более серьезно, чем еда.  Я ухожу за Биг Маком! 
