Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions cliff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@ breaking_always_bump_major = false

# header, body, and footer keys are Tera templates
# https://keats.github.io/tera/docs/#introduction
#
# The rule below is about the header template specifically, not about this
# file as a whole. Blank lines in the header are written as literal blank
# lines, never as trailing \n escapes: a TOML multi-line string already ends
# each source line with a newline, so an escape on top of that emits a second
# one. That doubling is invisible in the source and lands in the generated
# changelog as consecutive blank lines, which markdownlint rejects (MD012) in
# the changelog-autoupdate workflow.
#
# The body template is the opposite case. Its source lines are joined with
# trailing backslash continuations instead of emitting one output line each,
# so the \n escapes it uses to place newlines are deliberate.
header = """
<!-- markdownlint-configure-file { "no-duplicate-heading": false } -->\n
\n
# Changelog\n
All notable changes will be documented in this file. See [conventional commits](https://www.conventionalcommits.org) for commit guidelines.\n
The format is based on [Keep a Changelog](https://keepachangelog.com) and this project adheres to [Semantic Versioning](https://semver.org).\n
<!-- markdownlint-configure-file { "no-duplicate-heading": false } -->

# Changelog

All notable changes will be documented in this file. See [conventional commits](https://www.conventionalcommits.org) for commit guidelines.

The format is based on [Keep a Changelog](https://keepachangelog.com) and this project adheres to [Semantic Versioning](https://semver.org).

"""

body = """
Expand Down
104 changes: 104 additions & 0 deletions tests/test-cliff-header.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env bash
Comment thread
michen00 marked this conversation as resolved.
# Test script for the [changelog] header template in cliff.toml

set -uo pipefail
TEST_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Load shared configurations
# shellcheck disable=SC1091 # Dynamic path via $TEST_SCRIPT_DIR
. "$TEST_SCRIPT_DIR/colors.sh"

CLIFF_TOML="$TEST_SCRIPT_DIR/../cliff.toml"

PASSED=0
FAILED=0
Comment thread
michen00 marked this conversation as resolved.

pass() {
echo -e "${GREEN}✓${NC} $1"
((PASSED++))
}

fail() {
echo -e "${RED}✗${NC} $1"
shift
for msg in "$@"; do
echo -e " ${YELLOW}$msg${NC}"
done
((FAILED++))
}

# Render the header template the way TOML does, so the assertions below run
# against the text git-cliff actually writes. git-cliff is not installed on
# every machine that runs this suite (and not in CI at all), and the header is
# static text with no Tera expressions, so decoding it here is both sufficient
# and portable.
#
# TOML multi-line basic strings drop the newline right after the opening
# delimiter; every other source line contributes its text plus one newline, and
# a trailing \n escape contributes another newline on top of that. That second
# newline is easy to add by accident and invisible in the source, which is what
# MD012 below is guarding against.
render_header() {
awk '
/^header = """$/ { in_block = 1; next }
in_block && /^"""$/ { exit }
in_block {
Comment thread
michen00 marked this conversation as resolved.
line = $0
extra = 0
while (sub(/\\n$/, "", line)) extra++
if (line ~ /\\/) {
print "unsupported escape in header template: " $0 > "/dev/stderr"
exit 1
}
print line
for (i = 0; i < extra; i++) print ""
}
' "$1"
}

if ! work="$(mktemp -d)"; then
echo "Error: could not create a temporary directory" >&2
exit 1
fi
trap 'rm -rf "$work"' EXIT INT TERM HUP
rendered="$work/header.md"

if ! render_header "$CLIFF_TOML" >"$rendered"; then
fail "header template renders" "render_header could not decode the template"
elif [ ! -s "$rendered" ]; then
fail "header template renders" "Rendered header is empty; is the 'header = \"\"\"' block still there?"
else
pass "header template renders"

# MD012/no-multiple-blanks. markdownlint runs over the generated changelog
# in the changelog-autoupdate workflow, and a header that trips this rule
# fails that job every week without ever touching a commit.
#
# markdownlint counts a whitespace-only line as blank, so this check and
# the trailing-blank count below have to as well; testing for an empty
# line alone would pass a header that markdownlint still rejects.
offenders="$(awk 'BEGIN { run = 0 } { if ($0 ~ /^[[:space:]]*$/) { run++; if (run > 1) print NR } else run = 0 }' "$rendered")"
if [ -n "$offenders" ]; then
# shellcheck disable=SC2086 # Word splitting turns the line list into args
fail "header has no consecutive blank lines (MD012)" \
"Extra blank lines at rendered line(s): $(echo $offenders | tr ' ' ',')" \
"Rendered header:" \
"$(cat -v "$rendered")"
else
pass "header has no consecutive blank lines (MD012)"
fi

# The header has to end with exactly one blank line so the first '## ['
# section that follows it is separated by one blank line, not glued on.
trailing_blanks="$(awk '{ if ($0 ~ /^[[:space:]]*$/) blanks++; else blanks = 0 } END { print blanks + 0 }' "$rendered")"
if [ "$trailing_blanks" -ne 1 ]; then
fail "header ends with a single blank line" \
"Header ends with $trailing_blanks trailing blank line(s), expected 1"
else
pass "header ends with a single blank line"
fi
fi

echo ""
echo -e "Results: ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}"
[ "$FAILED" -eq 0 ]
Comment thread
michen00 marked this conversation as resolved.
1 change: 1 addition & 0 deletions tests/test-unit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ run_test "$TEST_SCRIPT_DIR/test-conventional-merge-commit.sh" "conventional-merg
run_test "$TEST_SCRIPT_DIR/test-parse-version.sh" "release/parse-version.sh tests"
run_test "$TEST_SCRIPT_DIR/test-bump-pins.sh" "release/bump-pins.sh tests"
run_test "$TEST_SCRIPT_DIR/test-stamp-changelog.sh" "release/stamp-changelog.sh tests"
run_test "$TEST_SCRIPT_DIR/test-cliff-header.sh" "cliff.toml changelog header tests"

# Summary
echo "=========================================="
Expand Down