mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
The auto-generated "Older Releases" index in CHANGELOG.md emitted dash bullets while the rest of the file uses asterisks, failing markdownlint MD004 (ul-style, consistent) with 49 errors. Switch the archive index generator to asterisk bullets, convert the existing entries, and align the unit test assertions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Filesystem operations on the ``docs/changelog/`` archive directory.
|
|
|
|
Provides three primitives the rest of the package builds on:
|
|
|
|
* :func:`existing_archives` lists the archive files on disk.
|
|
* :func:`archived_releases_from_directory` parses their filenames back
|
|
into ``(version, date)`` tuples sorted descending.
|
|
* :func:`build_index_section` renders the ``## Older Releases`` block
|
|
that links every archive file from the trimmed ``CHANGELOG.md``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import TYPE_CHECKING
|
|
|
|
from cli.contributing.changelog.archive.versioning import unpad_version
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
_ARCHIVE_FILENAME_RE = re.compile(
|
|
r"^\d{3}\.\d{3}\.\d{3}(?:[-+][^.]+)?-\d{4}-\d{2}-\d{2}\.md$"
|
|
)
|
|
_ARCHIVE_NAME_RE = re.compile(r"^(?P<padded>.+)-(?P<date>\d{4}-\d{2}-\d{2})\.md$")
|
|
|
|
|
|
def existing_archives(archive_dir: Path) -> list[Path]:
|
|
"""Return every archive file under *archive_dir* sorted descending
|
|
by filename. Returns ``[]`` when the directory does not exist.
|
|
"""
|
|
if not archive_dir.is_dir():
|
|
return []
|
|
return sorted(
|
|
(
|
|
p
|
|
for p in archive_dir.iterdir()
|
|
if p.is_file() and _ARCHIVE_FILENAME_RE.match(p.name)
|
|
),
|
|
reverse=True,
|
|
)
|
|
|
|
|
|
def archived_releases_from_directory(
|
|
archive_dir: Path,
|
|
) -> list[tuple[str, str]]:
|
|
"""Return ``(version, date)`` tuples for every archive file under
|
|
*archive_dir*, sorted descending so the newest release comes first.
|
|
"""
|
|
out: list[tuple[str, str]] = []
|
|
for path in existing_archives(archive_dir):
|
|
m = _ARCHIVE_NAME_RE.match(path.name)
|
|
if m is None:
|
|
continue
|
|
out.append((unpad_version(m.group("padded")), m.group("date")))
|
|
return out
|
|
|
|
|
|
def build_index_section(archive_dir: Path, repo_root: Path) -> str:
|
|
"""Render the ``## Older Releases`` block for the trimmed
|
|
``CHANGELOG.md``. Returns ``""`` when no archives exist.
|
|
"""
|
|
archives = existing_archives(archive_dir)
|
|
if not archives:
|
|
return ""
|
|
lines = ["## Older Releases", ""]
|
|
for path in archives:
|
|
rel = path.relative_to(repo_root).as_posix()
|
|
lines.append(f"* [{path.name}]({rel})")
|
|
return "\n".join(lines) + "\n"
|