Содержание

Генерация Debian changelog

Для автоматического формирования файла debian/changelog используется скрипт scripts/generate-changelog.sh.

Скрипт предназначен для подготовки Debian-пакета и формирует changelog на основании истории Git. Версия пакета берётся из CMakeLists.txt, а список изменений — из коммитов ветки develop, отсутствующих в ветке main.

▸ Исходный код

▾ Исходный код скрипта

#!/bin/bash
 
set -euo pipefail
 
PROJECT_NAME="pingfinder-msgd"
DEBIAN_REVISION="1"
 
# Get the repository root
REPO_ROOT=$(git rev-parse --show-toplevel)
 
CMAKE_FILE="${REPO_ROOT}/CMakeLists.txt"
CHANGELOG_FILE="${REPO_ROOT}/debian/changelog"
 
# Check current branch
CURRENT_BRANCH=$(git branch --show-current)
 
if [[ "$CURRENT_BRANCH" != "develop" ]]; then
    echo "Error: script must be run on the develop branch." >&2
    exit 1
fi
 
# Extract project version from CMakeLists.txt
VERSION=$(sed -nE \
    "s/^project\(${PROJECT_NAME}[[:space:]]+VERSION[[:space:]]+([0-9]+\.[0-9]+\.[0-9]+).*/\1/p" \
    "$CMAKE_FILE")
 
if [[ -z "$VERSION" ]]; then
    echo "Error: project version not found in $CMAKE_FILE." >&2
    exit 1
fi
 
echo "Project version: $VERSION"
 
# Find the latest release tag
LATEST_TAG=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-version:refname | head -n 1)
 
if [[ -n "$LATEST_TAG" ]]; then
    LATEST_VERSION="${LATEST_TAG#v}"
 
    echo "Latest release: $LATEST_TAG"
 
    if dpkg --compare-versions "$VERSION" lt "$LATEST_VERSION"; then
        echo "Error: project version $VERSION is older than latest release $LATEST_VERSION." >&2
        exit 1
    elif dpkg --compare-versions "$VERSION" eq "$LATEST_VERSION"; then
        echo "Version status: current release version."
    else
        echo "Version status: new release version."
    fi
else
    LATEST_VERSION=""
    echo "Latest release: none"
fi
 
# Find the latest Debian changelog update commit.
# This commit is the release point in develop.
RELEASE_POINT=$(git log -1 \
    --format='%H' \
    --grep='^Update Debian changelog for ')
 
if [[ -n "$RELEASE_POINT" ]]; then
    echo "Latest release point: $(git show -s --format='%s' "$RELEASE_POINT")"
else
    echo "Latest release point: none"
fi
 
# Get commits accumulated since the latest release point.
if [[ -n "$RELEASE_POINT" ]]; then
    LOG_RANGE="${RELEASE_POINT}..develop"
else
    LOG_RANGE="develop"
fi
 
COMMITS=$(git log "$LOG_RANGE" \
    --pretty=format:'%s' \
    --reverse \
    --grep='^Update Debian changelog for' \
    --invert-grep)
 
# Find the latest release preparation commit for the current version.
# It determines the date used in the Debian changelog.
RELEASE_COMMIT=$(git log -1 \
    --format='%H' \
    --grep="^Prepare release ${VERSION}$")
 
if [[ -z "$RELEASE_COMMIT" ]]; then
    echo "Error: release preparation commit not found for version $VERSION." >&2
    exit 1
fi
 
CHANGELOG_DATE=$(git show -s --format=%aD "$RELEASE_COMMIT")
 
# Handle absence of new commits
if [[ -z "$COMMITS" ]]; then
    if [[ -n "$LATEST_TAG" ]] && \
       dpkg --compare-versions "$VERSION" eq "$LATEST_VERSION"; then
        echo "No changes since the latest release."
    else
        echo "Error: no changes found since the previous release." >&2
        exit 1
    fi
fi
 
# Get maintainer information from Git configuration
MAINTAINER_NAME=$(git config user.name)
MAINTAINER_EMAIL=$(git config user.email)
 
if [[ -z "$MAINTAINER_NAME" || -z "$MAINTAINER_EMAIL" ]]; then
    echo "Error: Git user.name or user.email is not configured." >&2
    exit 1
fi
 
# Generate Debian changelog
{
    echo "$PROJECT_NAME (${VERSION}-${DEBIAN_REVISION}) unstable; urgency=medium"
    echo
 
    if [[ -n "$COMMITS" ]]; then
        while IFS= read -r commit; do
            echo "  * $commit"
        done <<< "$COMMITS"
    fi
 
    echo
    printf ' -- %s <%s>  %s\n' \
        "$MAINTAINER_NAME" \
        "$MAINTAINER_EMAIL" \
        "$CHANGELOG_DATE"
} > "$CHANGELOG_FILE"
 
echo "Generated $CHANGELOG_FILE:"
echo
cat "$CHANGELOG_FILE"


Условия запуска

Скрипт необходимо запускать из Git-репозитория проекта. Текущей веткой должна быть develop:

./generate-changelog.sh

Скрипт самостоятельно определяет корень репозитория, поэтому его можно запускать непосредственно из каталога scripts.

Для работы скрипта необходимы:

Версия проекта

Версия проекта определяется из строки project() файла CMakeLists.txt:

project(pingfinder-msgd VERSION 0.0.3)

Таким образом, CMakeLists.txt является единственным источником версии проекта. Версия в Debian-файлах отдельно не задаётся.

Скрипт также определяет последний release tag вида:

v<major>.<minor>.<patch>

и сравнивает его версию с версией из CMakeLists.txt.

Возможны три состояния:

Поэтому изменение версии в CMakeLists.txt выполняется непосредственно при подготовке нового релиза. Во время обычной разработки версия может совпадать с версией последнего выпущенного релиза.

Формирование списка изменений

В changelog попадают коммиты, которые присутствуют в develop, после предыдущего коммита Update Debian changelog for X.Y.Z, который выступает в роли Release point в ветке develop.

Принята следующая модель ветвления:

Сообщения коммитов сохраняются в исходном порядке и преобразуются в записи Debian changelog:

Предполагается, что сообщения коммитов должны быть достаточно информативными и понятными без дополнительного пояснения.

Формирование Debian changelog

На основании полученной информации создаётся файл: debian/changelog

Его заголовок имеет следующий вид:

pingfinder-msgd (0.0.3-1) unstable; urgency=medium

Здесь:

В конце записи указываются имя и email разработчика из настроек Git:

а также текущая дата в формате RFC 2822.