STANDARDS.md binds every repository in the NAPALM org: one default branch, Conventional Commits, the device-types contract, test-driven development, clean-code limits, a quality ratchet for existing code, packaging rules and releases by tag to PyPI. napalm-standard holds what a tool can check: the conformance check (with release rules on a tag), the quality ratchet (ported from netOrk's quality_ratchet.py), and the Gitea release from the CHANGELOG section. .gitea/workflows/driver.yml is the CI every driver calls; template/ is a new driver's starting point and passes the check as it is.
26 lines
1.0 KiB
Python
26 lines
1.0 KiB
Python
"""The CHANGELOG.md section of one version, the text of its release."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
#: A version heading in CHANGELOG.md: "## [1.2.3] - 2026-10-01".
|
|
_HEADING = re.compile(r"^## \[(?P<version>[^\]]+)\]", re.MULTILINE)
|
|
|
|
|
|
def changelog_section(text: str, version: str) -> str | None:
|
|
"""The body under ``## [version]`` up to the next version heading, or None."""
|
|
version = version.removeprefix("v")
|
|
headings = list(_HEADING.finditer(text))
|
|
for i, heading in enumerate(headings):
|
|
if heading.group("version") != version:
|
|
continue
|
|
line_end = text.find("\n", heading.end())
|
|
start = len(text) if line_end == -1 else line_end + 1
|
|
end = headings[i + 1].start() if i + 1 < len(headings) else len(text)
|
|
body = text[start:end].strip()
|
|
# Sections are sometimes closed by a horizontal rule; it is layout, not content.
|
|
body = re.sub(r"\n*^---\s*\Z", "", body, flags=re.MULTILINE).strip()
|
|
return body or None
|
|
return None
|