Статьи

Создание красивых заметок о выпуске с помощью git, gradle и markdown

В последние дни я спрашивал себя, как генерировать заметки о выпуске из информации, доступной в сообщениях коммитов / тегов от git.

Решения

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

  • Сообщения коммита должны быть написаны очень дисциплинированно
  • Маркер необходим для сбора сообщений, относящихся к релизу (для этого достаточно обычного тега)
  • Содержимое сообщений фиксации должно соответствовать соглашениям, чтобы функции , исправления и изменения можно было собирать и отображать в одном блоке.

Поэтому я использую аннотированные теги, которые должны содержать сообщение с тегом. Создать их довольно просто с помощью git

1
git tag -a v.1.0.0 -m "This is an annotated tag"

Sidenote: этот вид тегов имеет приятное дополнение, он позволяет проверить, какие коммиты принадлежат конкретному тегу.

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

Важный совет

Git обычно интерпретирует # как начало комментария. Аннотированные теги должны быть созданы с опцией –cleanup = verbatim, чтобы подавить эту функцию, если вы хотите использовать больше, чем первый и второй заголовок.

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

Реализация

Предпосылки

Поскольку я хочу также иметь красивую версию заметок о выпуске, я решил преобразовать уценку непосредственно в HTML-страницу. Для этого я использую PegDown в качестве процессора Markdown и загрузчик Twitter с темами bootswatch для стилизации вывода.

Скрипт начальной сборки

01
02
03
04
05
06
07
08
09
10
11
12
buildscript {
    repositories {
        mavenCentral()
        mavenLocal()
    }
    dependencies {
        classpath 'org.pegdown:pegdown:1.4.1'
    }
}
  
import org.pegdown.PegDownProcessor
import groovy.text.SimpleTemplateEngine

Реализация логики

Начнем с задачи контроля процесса генерации заметок о выпуске

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
task releaseNotes() {
    def releaseNotes = new File('releaseNotes.md')
    releaseNotes.delete()
    def versions = ""
    def tags = readTags()
    tags.each {tag ->
        versions += "- [$tag](#$tag)\n"
    }
  
    tags.each {tag ->
        releaseNotes << "# ${tag}<a name="$tag"></a>\n"
        def message = readTagMessage(tag)
        message.each{releaseNotes << "$it\n"}
        releaseNotes << "\n"
    }
  
    def writer = new StringWriter()
    def pdp = new PegDownProcessor()
    def engine = new SimpleTemplateEngine()
    def template = engine.createTemplate(new File("releaseNotes.tpl"))
    def daten = [releaseNotes:pdp.markdownToHtml(new File("releaseNotes.md").text), application: project.name, versions:pdp.markdownToHtml(versions)]
  
    def ergebnis = template.make(daten)
    new File('releaseNotes.html').withWriter { w ->
        w.write(ergebnis)
    }
}

Процесс действительно прост.

  • Сначала мы очищаем старые артефакты из файла уценки (строки 2 и 3). После этого мы создали раздел Версии, загрузили доступные теги (строки 5–10) и поместили все в отдельный список.
  • Затем мы создаем информацию о заметках о выпуске и добавляем заголовок для каждого тега, за которым следует сообщение, принадлежащее этому тегу (строки с 12 по 18).
  • В качестве последнего шага мы анализируем файл уценки и создаем HTML-страницу, передавая проанализированные значения в шаблон.

Как видите, требуется еще три компонента

  1. метод readTags
  2. метод readTagMessage
  3. шаблон для HTML-страницы

readTags

Этот метод вызывает:

1
git tag -l

и возвращает упорядоченный список тегов

1
2
3
4
5
6
7
8
def readTags() {
    def tags = []
    def proc = "git tag -l".execute()
    proc.in.eachLine { line -> tags += line}
    tags.sort {}
    Collections.reverse( tags )
    tags
}

readTagMessage

Этот метод использует

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
def readTagMessage(String tag) {
    def message = []
    def proc = "git cat-file tag $tag".execute()
    def startCollection = false
    proc.in.eachLine { line ->
        if (line.isEmpty()) {
            startCollection = true
        }
        if (startCollection) {
            message += line
        }
    }
    proc.err.eachLine { line -> println line }
    message
}

releaseNotes.tpl

Этот шаблон содержит три свойства приложения, releaseNotes и версии . Приложение заменяется именем вашего приложения и используется в заголовке. releaseNotes содержит преобразованные заметки о выпуске. И, наконец, версия представляет:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xml:lang='de' xmlns='http://www.w3.org/1999/xhtml' lang='de'>
    <head>
        <title>Release Notes of $application</title>
        <link rel="stylesheet" href="http://bootswatch.com/yeti/bootstrap.min.css">
        <style type="text/css">
        .releasenotes h1 {
          font-size: 1.5em;
        }
        .releasenotes h2 {
          font-size: 1.2em;
        }
      </style>
    </head>
    <body>
      <div class="row">
      <div class="navbar navbar-default">
        <div class="col-md-4"></div>
        <div class="col-md-4">
          <h1>Releasenotes</h1>
        </div>
        <div class="col-md-4"></div>
      </div>
      </div>
        <div class="row releasenotes">
            <div class="col-md-4"></div>
            <div class="col-md-4">$releaseNotes</div>
            <div class="col-md-4"><h1>Versions</h1>$versions</div>
        </div>
    </body>
</html>

Как уже указывалось в предварительных требованиях, Twitter Bootstrap и тема из bootswatch применяются для украшения кода.

окончательный

Собрав все вместе, мы можем создать аннотированный тег и просто вызвать

1
gradle releaseNotes

и Gradle прочитает все сообщения и теги и создаст два файла

  • releaseNotes.md и
  • releaseNotes.html ( Пример — спасибо моему коллеге за его мысли о макете и дизайне для этой версии)

Вывод

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

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